SpyBara
Go Premium Account
2026
31 Jan 2026, 03:42
12 May 2026, 14:59 12 May 2026, 01:59 12 May 2026, 00:01 11 May 2026, 23:00 11 May 2026, 21:57 11 May 2026, 20:02 11 May 2026, 18:59 11 May 2026, 18:00 11 May 2026, 15:00 10 May 2026, 23:03 10 May 2026, 17:00 10 May 2026, 04:02 9 May 2026, 04:57 9 May 2026, 04:01 9 May 2026, 03:01 8 May 2026, 22:00 8 May 2026, 19:00 8 May 2026, 18:00 8 May 2026, 16:57 8 May 2026, 07:02 8 May 2026, 06:02 8 May 2026, 03:01 8 May 2026, 02:03 8 May 2026, 01:02 8 May 2026, 00:02 7 May 2026, 22:59 7 May 2026, 21:57 7 May 2026, 17:08 5 May 2026, 23:00 5 May 2026, 21:00 5 May 2026, 17:00 5 May 2026, 15:59 5 May 2026, 14:57 5 May 2026, 00:02 4 May 2026, 22:58 4 May 2026, 22:01 4 May 2026, 18:58 4 May 2026, 15:35 4 May 2026, 06:55 4 May 2026, 04:18 2 May 2026, 18:14 2 May 2026, 04:05 2 May 2026, 00:19 1 May 2026, 18:19 1 May 2026, 04:22 1 May 2026, 00:20 29 Apr 2026, 21:21 29 Apr 2026, 15:36 29 Apr 2026, 09:39 29 Apr 2026, 04:11 29 Apr 2026, 00:20 28 Apr 2026, 21:21 28 Apr 2026, 18:28 28 Apr 2026, 15:45 28 Apr 2026, 06:49 27 Apr 2026, 21:20 27 Apr 2026, 18:23 26 Apr 2026, 04:08 25 Apr 2026, 21:10 24 Apr 2026, 18:11 24 Apr 2026, 06:34 24 Apr 2026, 00:17 23 Apr 2026, 18:19 23 Apr 2026, 04:04 23 Apr 2026, 00:17 22 Apr 2026, 21:15 22 Apr 2026, 04:00 22 Apr 2026, 00:13 21 Apr 2026, 21:14 21 Apr 2026, 09:30 21 Apr 2026, 04:01 20 Apr 2026, 21:14 20 Apr 2026, 18:16 18 Apr 2026, 18:09 18 Apr 2026, 00:13 17 Apr 2026, 21:13 17 Apr 2026, 18:14 17 Apr 2026, 00:15 16 Apr 2026, 21:13 16 Apr 2026, 18:21 16 Apr 2026, 15:30 16 Apr 2026, 04:02 16 Apr 2026, 00:16 15 Apr 2026, 18:20 15 Apr 2026, 15:24 15 Apr 2026, 09:29 15 Apr 2026, 04:00 14 Apr 2026, 21:14 14 Apr 2026, 18:21 14 Apr 2026, 06:32 14 Apr 2026, 04:00 14 Apr 2026, 00:16 13 Apr 2026, 21:14 13 Apr 2026, 18:21 11 Apr 2026, 00:11 10 Apr 2026, 21:09 10 Apr 2026, 18:13 10 Apr 2026, 06:32 10 Apr 2026, 00:12 9 Apr 2026, 21:14 9 Apr 2026, 18:17 9 Apr 2026, 15:29 9 Apr 2026, 03:55 9 Apr 2026, 00:09 8 Apr 2026, 21:13 8 Apr 2026, 18:21 8 Apr 2026, 15:27 8 Apr 2026, 00:12 7 Apr 2026, 21:14 4 Apr 2026, 18:05 4 Apr 2026, 03:46 4 Apr 2026, 00:09 3 Apr 2026, 21:07 3 Apr 2026, 18:08 3 Apr 2026, 03:54 3 Apr 2026, 00:11 2 Apr 2026, 21:08 2 Apr 2026, 18:12 2 Apr 2026, 09:19 2 Apr 2026, 06:21 2 Apr 2026, 03:53 1 Apr 2026, 21:12 1 Apr 2026, 18:13 1 Apr 2026, 04:00 1 Apr 2026, 00:11 31 Mar 2026, 21:09 31 Mar 2026, 06:24 31 Mar 2026, 03:56 31 Mar 2026, 00:11 30 Mar 2026, 21:13 30 Mar 2026, 18:15 28 Mar 2026, 18:04 28 Mar 2026, 15:06 27 Mar 2026, 21:09 27 Mar 2026, 18:14 27 Mar 2026, 15:15 27 Mar 2026, 06:21 27 Mar 2026, 03:56 27 Mar 2026, 00:10 26 Mar 2026, 21:07 26 Mar 2026, 18:16 26 Mar 2026, 15:25 26 Mar 2026, 06:21 26 Mar 2026, 03:55 26 Mar 2026, 00:10 25 Mar 2026, 21:08 25 Mar 2026, 18:15 25 Mar 2026, 06:18 25 Mar 2026, 03:47 25 Mar 2026, 00:08 24 Mar 2026, 18:15 24 Mar 2026, 00:07 23 Mar 2026, 21:08 23 Mar 2026, 18:13 23 Mar 2026, 00:09 22 Mar 2026, 18:04 22 Mar 2026, 00:07 21 Mar 2026, 18:03 21 Mar 2026, 00:07 20 Mar 2026, 21:05 20 Mar 2026, 18:08 20 Mar 2026, 15:13 20 Mar 2026, 03:45 20 Mar 2026, 00:08 19 Mar 2026, 06:17 19 Mar 2026, 00:08 18 Mar 2026, 18:16 18 Mar 2026, 12:11 18 Mar 2026, 09:15 18 Mar 2026, 03:50 18 Mar 2026, 00:09 17 Mar 2026, 21:10 17 Mar 2026, 18:15 17 Mar 2026, 03:46 17 Mar 2026, 00:08 16 Mar 2026, 21:10 16 Mar 2026, 18:15 14 Mar 2026, 03:44 14 Mar 2026, 00:08 13 Mar 2026, 21:07 13 Mar 2026, 18:07 13 Mar 2026, 06:12 12 Mar 2026, 21:07 12 Mar 2026, 18:12 12 Mar 2026, 00:07 11 Mar 2026, 03:43 11 Mar 2026, 00:05 10 Mar 2026, 03:43 10 Mar 2026, 00:05 9 Mar 2026, 21:06 7 Mar 2026, 03:37 7 Mar 2026, 00:07 6 Mar 2026, 06:10 6 Mar 2026, 03:44 6 Mar 2026, 00:12 5 Mar 2026, 06:12 5 Mar 2026, 03:45 5 Mar 2026, 00:07 4 Mar 2026, 21:06 4 Mar 2026, 18:09 4 Mar 2026, 09:09 1 Mar 2026, 06:10 1 Mar 2026, 03:49 28 Feb 2026, 21:01 28 Feb 2026, 00:05 27 Feb 2026, 21:05 27 Feb 2026, 18:07 27 Feb 2026, 09:11 27 Feb 2026, 06:13 27 Feb 2026, 00:08 26 Feb 2026, 21:08 26 Feb 2026, 18:12 26 Feb 2026, 09:14 26 Feb 2026, 06:17 26 Feb 2026, 00:07 25 Feb 2026, 03:47 25 Feb 2026, 00:09 24 Feb 2026, 21:08 24 Feb 2026, 18:15 23 Feb 2026, 21:13 21 Feb 2026, 18:03 21 Feb 2026, 06:08 20 Feb 2026, 21:03 20 Feb 2026, 06:14 20 Feb 2026, 00:07 19 Feb 2026, 21:06 19 Feb 2026, 03:48 19 Feb 2026, 00:08 18 Feb 2026, 03:48 17 Feb 2026, 21:08 17 Feb 2026, 00:08 16 Feb 2026, 21:05 14 Feb 2026, 03:44 13 Feb 2026, 21:09 12 Feb 2026, 00:06 11 Feb 2026, 21:10 11 Feb 2026, 00:11 10 Feb 2026, 21:13 10 Feb 2026, 03:56 10 Feb 2026, 00:11 9 Feb 2026, 15:17 9 Feb 2026, 00:08 7 Feb 2026, 21:05 7 Feb 2026, 18:03 7 Feb 2026, 03:43 6 Feb 2026, 21:06 6 Feb 2026, 00:05 5 Feb 2026, 21:06 5 Feb 2026, 18:13 5 Feb 2026, 03:46 5 Feb 2026, 00:07 4 Feb 2026, 21:07 4 Feb 2026, 18:11 4 Feb 2026, 03:45 4 Feb 2026, 00:06 3 Feb 2026, 21:08 3 Feb 2026, 18:14 3 Feb 2026, 09:10 3 Feb 2026, 03:46 1 Feb 2026, 21:03 1 Feb 2026, 18:02 31 Jan 2026, 03:42 31 Jan 2026, 00:06 30 Jan 2026, 18:07 30 Jan 2026, 00:06 29 Jan 2026, 21:03 28 Jan 2026, 15:06 28 Jan 2026, 03:30 28 Jan 2026, 00:05 27 Jan 2026, 21:01 27 Jan 2026, 18:03 27 Jan 2026, 06:02 26 Jan 2026, 21:03 25 Jan 2026, 03:34 24 Jan 2026, 03:29 23 Jan 2026, 21:01 23 Jan 2026, 18:02 23 Jan 2026, 00:05 22 Jan 2026, 21:03 22 Jan 2026, 15:05 22 Jan 2026, 03:31 22 Jan 2026, 00:05 21 Jan 2026, 21:05 21 Jan 2026, 06:02 21 Jan 2026, 03:30 21 Jan 2026, 00:05 20 Jan 2026, 21:03 20 Jan 2026, 18:03 20 Jan 2026, 15:05 20 Jan 2026, 03:30 19 Jan 2026, 21:01 19 Jan 2026, 00:05 16 Jan 2026, 21:01 16 Jan 2026, 18:02 16 Jan 2026, 15:02 16 Jan 2026, 00:05 14 Jan 2026, 06:02 14 Jan 2026, 00:05 12 Jan 2026, 21:02 12 Jan 2026, 18:02 12 Jan 2026, 00:05 11 Jan 2026, 18:02 11 Jan 2026, 03:31 11 Jan 2026, 00:06 10 Jan 2026, 21:01 10 Jan 2026, 03:29 10 Jan 2026, 00:04 9 Jan 2026, 21:01 9 Jan 2026, 00:04 8 Jan 2026, 21:02 8 Jan 2026, 06:02 8 Jan 2026, 03:29 8 Jan 2026, 00:05 7 Jan 2026, 21:01 7 Jan 2026, 18:02 7 Jan 2026, 09:05 7 Jan 2026, 06:02 7 Jan 2026, 03:30 7 Jan 2026, 00:04 6 Jan 2026, 21:01 6 Jan 2026, 03:29 6 Jan 2026, 00:05 3 Jan 2026, 18:02 27 Dec 2025, 06:02 27 Dec 2025, 03:28 23 Dec 2025, 18:02 20 Dec 2025, 00:04 19 Dec 2025, 21:01 19 Dec 2025, 18:02 19 Dec 2025, 00:05 18 Dec 2025, 21:01 18 Dec 2025, 18:02 18 Dec 2025, 15:02 17 Dec 2025, 15:02 17 Dec 2025, 03:27 16 Dec 2025, 21:01 16 Dec 2025, 18:02 16 Dec 2025, 00:05 15 Dec 2025, 21:01 15 Dec 2025, 18:02 13 Dec 2025, 06:02 12 Dec 2025, 21:01 12 Dec 2025, 00:05 11 Dec 2025, 21:02 11 Dec 2025, 18:01 11 Dec 2025, 06:02 10 Dec 2025, 09:03 9 Dec 2025, 18:01 9 Dec 2025, 06:02 9 Dec 2025, 03:25 8 Dec 2025, 21:01 8 Dec 2025, 06:02 8 Dec 2025, 00:05 6 Dec 2025, 18:02 5 Dec 2025, 00:04 4 Dec 2025, 21:02 4 Dec 2025, 18:02 4 Dec 2025, 06:02 4 Dec 2025, 03:26 3 Dec 2025, 00:04 2 Dec 2025, 21:01 2 Dec 2025, 00:04 1 Dec 2025, 03:31 27 Nov 2025, 06:02 27 Nov 2025, 03:20 26 Nov 2025, 00:04 25 Nov 2025, 03:22 24 Nov 2025, 21:01 21 Nov 2025, 00:04 20 Nov 2025, 18:02 20 Nov 2025, 06:02 20 Nov 2025, 03:20 19 Nov 2025, 03:21 19 Nov 2025, 00:05 18 Nov 2025, 18:02 18 Nov 2025, 09:02 18 Nov 2025, 03:21 17 Nov 2025, 03:24 17 Nov 2025, 00:04 16 Nov 2025, 00:04 14 Nov 2025, 21:26 6 Nov 2025, 18:02 6 Nov 2025, 15:02 6 Nov 2025, 12:02 6 Nov 2025, 06:01 6 Nov 2025, 03:22 4 Nov 2025, 18:02 4 Nov 2025, 03:19 4 Nov 2025, 00:04 3 Nov 2025, 21:01 3 Nov 2025, 12:03 3 Nov 2025, 09:02 3 Nov 2025, 06:02 3 Nov 2025, 03:24 3 Nov 2025, 00:04 2 Nov 2025, 18:01 2 Nov 2025, 12:02 2 Nov 2025, 09:01 1 Nov 2025, 21:01 31 Oct 2025, 00:04 30 Oct 2025, 18:02 29 Oct 2025, 21:02 28 Oct 2025, 18:02 27 Oct 2025, 18:02 24 Oct 2025, 21:01 23 Oct 2025, 21:02 23 Oct 2025, 09:02 23 Oct 2025, 06:02 23 Oct 2025, 00:04 21 Oct 2025, 00:04 20 Oct 2025, 21:02 20 Oct 2025, 15:12 20 Oct 2025, 00:05 17 Oct 2025, 18:01 17 Oct 2025, 12:03 16 Oct 2025, 18:02 16 Oct 2025, 00:05 15 Oct 2025, 18:02 13 Oct 2025, 21:01 12 Oct 2025, 18:01
27 Apr 2026, 21:20
12 May 2026, 14:59 12 May 2026, 01:59 12 May 2026, 00:01 11 May 2026, 23:00 11 May 2026, 21:57 11 May 2026, 20:02 11 May 2026, 18:59 11 May 2026, 18:00 11 May 2026, 15:00 10 May 2026, 23:03 10 May 2026, 17:00 10 May 2026, 04:02 9 May 2026, 04:57 9 May 2026, 04:01 9 May 2026, 03:01 8 May 2026, 22:00 8 May 2026, 19:00 8 May 2026, 18:00 8 May 2026, 16:57 8 May 2026, 07:02 8 May 2026, 06:02 8 May 2026, 03:01 8 May 2026, 02:03 8 May 2026, 01:02 8 May 2026, 00:02 7 May 2026, 22:59 7 May 2026, 21:57 7 May 2026, 17:08 5 May 2026, 23:00 5 May 2026, 21:00 5 May 2026, 17:00 5 May 2026, 15:59 5 May 2026, 14:57 5 May 2026, 00:02 4 May 2026, 22:58 4 May 2026, 22:01 4 May 2026, 18:58 4 May 2026, 15:35 4 May 2026, 06:55 4 May 2026, 04:18 2 May 2026, 18:14 2 May 2026, 04:05 2 May 2026, 00:19 1 May 2026, 18:19 1 May 2026, 04:22 1 May 2026, 00:20 29 Apr 2026, 21:21 29 Apr 2026, 15:36 29 Apr 2026, 09:39 29 Apr 2026, 04:11 29 Apr 2026, 00:20 28 Apr 2026, 21:21 28 Apr 2026, 18:28 28 Apr 2026, 15:45 28 Apr 2026, 06:49 27 Apr 2026, 21:20 27 Apr 2026, 18:23 26 Apr 2026, 04:08 25 Apr 2026, 21:10 24 Apr 2026, 18:11 24 Apr 2026, 06:34 24 Apr 2026, 00:17 23 Apr 2026, 18:19 23 Apr 2026, 04:04 23 Apr 2026, 00:17 22 Apr 2026, 21:15 22 Apr 2026, 04:00 22 Apr 2026, 00:13 21 Apr 2026, 21:14 21 Apr 2026, 09:30 21 Apr 2026, 04:01 20 Apr 2026, 21:14 20 Apr 2026, 18:16 18 Apr 2026, 18:09 18 Apr 2026, 00:13 17 Apr 2026, 21:13 17 Apr 2026, 18:14 17 Apr 2026, 00:15 16 Apr 2026, 21:13 16 Apr 2026, 18:21 16 Apr 2026, 15:30 16 Apr 2026, 04:02 16 Apr 2026, 00:16 15 Apr 2026, 18:20 15 Apr 2026, 15:24 15 Apr 2026, 09:29 15 Apr 2026, 04:00 14 Apr 2026, 21:14 14 Apr 2026, 18:21 14 Apr 2026, 06:32 14 Apr 2026, 04:00 14 Apr 2026, 00:16 13 Apr 2026, 21:14 13 Apr 2026, 18:21 11 Apr 2026, 00:11 10 Apr 2026, 21:09 10 Apr 2026, 18:13 10 Apr 2026, 06:32 10 Apr 2026, 00:12 9 Apr 2026, 21:14 9 Apr 2026, 18:17 9 Apr 2026, 15:29 9 Apr 2026, 03:55 9 Apr 2026, 00:09 8 Apr 2026, 21:13 8 Apr 2026, 18:21 8 Apr 2026, 15:27 8 Apr 2026, 00:12 7 Apr 2026, 21:14 4 Apr 2026, 18:05 4 Apr 2026, 03:46 4 Apr 2026, 00:09 3 Apr 2026, 21:07 3 Apr 2026, 18:08 3 Apr 2026, 03:54 3 Apr 2026, 00:11 2 Apr 2026, 21:08 2 Apr 2026, 18:12 2 Apr 2026, 09:19 2 Apr 2026, 06:21 2 Apr 2026, 03:53 1 Apr 2026, 21:12 1 Apr 2026, 18:13 1 Apr 2026, 04:00 1 Apr 2026, 00:11 31 Mar 2026, 21:09 31 Mar 2026, 06:24 31 Mar 2026, 03:56 31 Mar 2026, 00:11 30 Mar 2026, 21:13 30 Mar 2026, 18:15 28 Mar 2026, 18:04 28 Mar 2026, 15:06 27 Mar 2026, 21:09 27 Mar 2026, 18:14 27 Mar 2026, 15:15 27 Mar 2026, 06:21 27 Mar 2026, 03:56 27 Mar 2026, 00:10 26 Mar 2026, 21:07 26 Mar 2026, 18:16 26 Mar 2026, 15:25 26 Mar 2026, 06:21 26 Mar 2026, 03:55 26 Mar 2026, 00:10 25 Mar 2026, 21:08 25 Mar 2026, 18:15 25 Mar 2026, 06:18 25 Mar 2026, 03:47 25 Mar 2026, 00:08 24 Mar 2026, 18:15 24 Mar 2026, 00:07 23 Mar 2026, 21:08 23 Mar 2026, 18:13 23 Mar 2026, 00:09 22 Mar 2026, 18:04 22 Mar 2026, 00:07 21 Mar 2026, 18:03 21 Mar 2026, 00:07 20 Mar 2026, 21:05 20 Mar 2026, 18:08 20 Mar 2026, 15:13 20 Mar 2026, 03:45 20 Mar 2026, 00:08 19 Mar 2026, 06:17 19 Mar 2026, 00:08 18 Mar 2026, 18:16 18 Mar 2026, 12:11 18 Mar 2026, 09:15 18 Mar 2026, 03:50 18 Mar 2026, 00:09 17 Mar 2026, 21:10 17 Mar 2026, 18:15 17 Mar 2026, 03:46 17 Mar 2026, 00:08 16 Mar 2026, 21:10 16 Mar 2026, 18:15 14 Mar 2026, 03:44 14 Mar 2026, 00:08 13 Mar 2026, 21:07 13 Mar 2026, 18:07 13 Mar 2026, 06:12 12 Mar 2026, 21:07 12 Mar 2026, 18:12 12 Mar 2026, 00:07 11 Mar 2026, 03:43 11 Mar 2026, 00:05 10 Mar 2026, 03:43 10 Mar 2026, 00:05 9 Mar 2026, 21:06 7 Mar 2026, 03:37 7 Mar 2026, 00:07 6 Mar 2026, 06:10 6 Mar 2026, 03:44 6 Mar 2026, 00:12 5 Mar 2026, 06:12 5 Mar 2026, 03:45 5 Mar 2026, 00:07 4 Mar 2026, 21:06 4 Mar 2026, 18:09 4 Mar 2026, 09:09 1 Mar 2026, 06:10 1 Mar 2026, 03:49 28 Feb 2026, 21:01 28 Feb 2026, 00:05 27 Feb 2026, 21:05 27 Feb 2026, 18:07 27 Feb 2026, 09:11 27 Feb 2026, 06:13 27 Feb 2026, 00:08 26 Feb 2026, 21:08 26 Feb 2026, 18:12 26 Feb 2026, 09:14 26 Feb 2026, 06:17 26 Feb 2026, 00:07 25 Feb 2026, 03:47 25 Feb 2026, 00:09 24 Feb 2026, 21:08 24 Feb 2026, 18:15 23 Feb 2026, 21:13 21 Feb 2026, 18:03 21 Feb 2026, 06:08 20 Feb 2026, 21:03 20 Feb 2026, 06:14 20 Feb 2026, 00:07 19 Feb 2026, 21:06 19 Feb 2026, 03:48 19 Feb 2026, 00:08 18 Feb 2026, 03:48 17 Feb 2026, 21:08 17 Feb 2026, 00:08 16 Feb 2026, 21:05 14 Feb 2026, 03:44 13 Feb 2026, 21:09 12 Feb 2026, 00:06 11 Feb 2026, 21:10 11 Feb 2026, 00:11 10 Feb 2026, 21:13 10 Feb 2026, 03:56 10 Feb 2026, 00:11 9 Feb 2026, 15:17 9 Feb 2026, 00:08 7 Feb 2026, 21:05 7 Feb 2026, 18:03 7 Feb 2026, 03:43 6 Feb 2026, 21:06 6 Feb 2026, 00:05 5 Feb 2026, 21:06 5 Feb 2026, 18:13 5 Feb 2026, 03:46 5 Feb 2026, 00:07 4 Feb 2026, 21:07 4 Feb 2026, 18:11 4 Feb 2026, 03:45 4 Feb 2026, 00:06 3 Feb 2026, 21:08 3 Feb 2026, 18:14 3 Feb 2026, 09:10 3 Feb 2026, 03:46 1 Feb 2026, 21:03 1 Feb 2026, 18:02 31 Jan 2026, 03:42 31 Jan 2026, 00:06 30 Jan 2026, 18:07 30 Jan 2026, 00:06 29 Jan 2026, 21:03 28 Jan 2026, 15:06 28 Jan 2026, 03:30 28 Jan 2026, 00:05 27 Jan 2026, 21:01 27 Jan 2026, 18:03 27 Jan 2026, 06:02 26 Jan 2026, 21:03 25 Jan 2026, 03:34 24 Jan 2026, 03:29 23 Jan 2026, 21:01 23 Jan 2026, 18:02 23 Jan 2026, 00:05 22 Jan 2026, 21:03 22 Jan 2026, 15:05 22 Jan 2026, 03:31 22 Jan 2026, 00:05 21 Jan 2026, 21:05 21 Jan 2026, 06:02 21 Jan 2026, 03:30 21 Jan 2026, 00:05 20 Jan 2026, 21:03 20 Jan 2026, 18:03 20 Jan 2026, 15:05 20 Jan 2026, 03:30 19 Jan 2026, 21:01 19 Jan 2026, 00:05 16 Jan 2026, 21:01 16 Jan 2026, 18:02 16 Jan 2026, 15:02 16 Jan 2026, 00:05 14 Jan 2026, 06:02 14 Jan 2026, 00:05 12 Jan 2026, 21:02 12 Jan 2026, 18:02 12 Jan 2026, 00:05 11 Jan 2026, 18:02 11 Jan 2026, 03:31 11 Jan 2026, 00:06 10 Jan 2026, 21:01 10 Jan 2026, 03:29 10 Jan 2026, 00:04 9 Jan 2026, 21:01 9 Jan 2026, 00:04 8 Jan 2026, 21:02 8 Jan 2026, 06:02 8 Jan 2026, 03:29 8 Jan 2026, 00:05 7 Jan 2026, 21:01 7 Jan 2026, 18:02 7 Jan 2026, 09:05 7 Jan 2026, 06:02 7 Jan 2026, 03:30 7 Jan 2026, 00:04 6 Jan 2026, 21:01 6 Jan 2026, 03:29 6 Jan 2026, 00:05 3 Jan 2026, 18:02 27 Dec 2025, 06:02 27 Dec 2025, 03:28 23 Dec 2025, 18:02 20 Dec 2025, 00:04 19 Dec 2025, 21:01 19 Dec 2025, 18:02 19 Dec 2025, 00:05 18 Dec 2025, 21:01 18 Dec 2025, 18:02 18 Dec 2025, 15:02 17 Dec 2025, 15:02 17 Dec 2025, 03:27 16 Dec 2025, 21:01 16 Dec 2025, 18:02 16 Dec 2025, 00:05 15 Dec 2025, 21:01 15 Dec 2025, 18:02 13 Dec 2025, 06:02 12 Dec 2025, 21:01 12 Dec 2025, 00:05 11 Dec 2025, 21:02 11 Dec 2025, 18:01 11 Dec 2025, 06:02 10 Dec 2025, 09:03 9 Dec 2025, 18:01 9 Dec 2025, 06:02 9 Dec 2025, 03:25 8 Dec 2025, 21:01 8 Dec 2025, 06:02 8 Dec 2025, 00:05 6 Dec 2025, 18:02 5 Dec 2025, 00:04 4 Dec 2025, 21:02 4 Dec 2025, 18:02 4 Dec 2025, 06:02 4 Dec 2025, 03:26 3 Dec 2025, 00:04 2 Dec 2025, 21:01 2 Dec 2025, 00:04 1 Dec 2025, 03:31 27 Nov 2025, 06:02 27 Nov 2025, 03:20 26 Nov 2025, 00:04 25 Nov 2025, 03:22 24 Nov 2025, 21:01 21 Nov 2025, 00:04 20 Nov 2025, 18:02 20 Nov 2025, 06:02 20 Nov 2025, 03:20 19 Nov 2025, 03:21 19 Nov 2025, 00:05 18 Nov 2025, 18:02 18 Nov 2025, 09:02 18 Nov 2025, 03:21 17 Nov 2025, 03:24 17 Nov 2025, 00:04 16 Nov 2025, 00:04 14 Nov 2025, 21:26 6 Nov 2025, 18:02 6 Nov 2025, 15:02 6 Nov 2025, 12:02 6 Nov 2025, 06:01 6 Nov 2025, 03:22 4 Nov 2025, 18:02 4 Nov 2025, 03:19 4 Nov 2025, 00:04 3 Nov 2025, 21:01 3 Nov 2025, 12:03 3 Nov 2025, 09:02 3 Nov 2025, 06:02 3 Nov 2025, 03:24 3 Nov 2025, 00:04 2 Nov 2025, 18:01 2 Nov 2025, 12:02 2 Nov 2025, 09:01 1 Nov 2025, 21:01 31 Oct 2025, 00:04 30 Oct 2025, 18:02 29 Oct 2025, 21:02 28 Oct 2025, 18:02 27 Oct 2025, 18:02 24 Oct 2025, 21:01 23 Oct 2025, 21:02 23 Oct 2025, 09:02 23 Oct 2025, 06:02 23 Oct 2025, 00:04 21 Oct 2025, 00:04 20 Oct 2025, 21:02 20 Oct 2025, 15:12 20 Oct 2025, 00:05 17 Oct 2025, 18:01 17 Oct 2025, 12:03 16 Oct 2025, 18:02 16 Oct 2025, 00:05 15 Oct 2025, 18:02 13 Oct 2025, 21:01 12 Oct 2025, 18:01
Wed 1 00:11 Wed 1 04:00 Wed 1 18:13 Wed 1 21:12 Thu 2 03:53 Thu 2 06:21 Thu 2 09:19 Thu 2 18:12 Thu 2 21:08 Fri 3 00:11 Fri 3 03:54 Fri 3 18:08 Fri 3 21:07 Sat 4 00:09 Sat 4 03:46 Sat 4 18:05 Tue 7 21:14 Wed 8 00:12 Wed 8 15:27 Wed 8 18:21 Wed 8 21:13 Thu 9 00:09 Thu 9 03:55 Thu 9 15:29 Thu 9 18:17 Thu 9 21:14 Fri 10 00:12 Fri 10 06:32 Fri 10 18:13 Fri 10 21:09 Sat 11 00:11 Mon 13 18:21 Mon 13 21:14 Tue 14 00:16 Tue 14 04:00 Tue 14 06:32 Tue 14 18:21 Tue 14 21:14 Wed 15 04:00 Wed 15 09:29 Wed 15 15:24 Wed 15 18:20 Thu 16 00:16 Thu 16 04:02 Thu 16 15:30 Thu 16 18:21 Thu 16 21:13 Fri 17 00:15 Fri 17 18:14 Fri 17 21:13 Sat 18 00:13 Sat 18 18:09 Mon 20 18:16 Mon 20 21:14 Tue 21 04:01 Tue 21 09:30 Tue 21 21:14 Wed 22 00:13 Wed 22 04:00 Wed 22 21:15 Thu 23 00:17 Thu 23 04:04 Thu 23 18:19 Fri 24 00:17 Fri 24 06:34 Fri 24 18:11 Sat 25 21:10 Sun 26 04:08 Mon 27 18:23 Mon 27 21:20 Tue 28 06:49 Tue 28 15:45 Tue 28 18:28 Tue 28 21:21 Wed 29 00:20 Wed 29 04:11 Wed 29 09:39 Wed 29 15:36 Wed 29 21:21

admin-setup.md +132 −0 added

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# Set up Claude Code for your organization

6 

7> A decision map for administrators deploying Claude Code, covering API providers, managed settings, policy enforcement, usage monitoring, and data handling.

8 

9Claude Code enforces organization policy through managed settings that take precedence over local developer configuration. You deliver those settings from the Claude admin console, your mobile device management (MDM) system, or a file on disk. The settings control which tools, commands, servers, and network destinations Claude can reach.

10 

11This page walks through the deployment decisions in order. Each row links to the section below and to the reference page for that area.

12 

13<Note>

14 SSO, SCIM provisioning, and seat assignment are configured at the Claude account level. See the [Claude Enterprise Administrator Guide](https://claude.com/resources/tutorials/claude-enterprise-administrator-guide) and [seat assignment](https://support.claude.com/en/articles/11845131-use-claude-code-with-your-team-or-enterprise-plan) for those steps.

15</Note>

16 

17| Decision | What you're choosing | Reference |

18| :---------------------------------------------------------------------- | :-------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- |

19| [Choose your API provider](#choose-your-api-provider) | Where Claude Code authenticates and how it's billed | [Authentication](/en/authentication), [Bedrock](/en/amazon-bedrock), [Vertex AI](/en/google-vertex-ai), [Foundry](/en/microsoft-foundry) |

20| [Decide how settings reach devices](#decide-how-settings-reach-devices) | How managed policy reaches developer machines | [Server-managed settings](/en/server-managed-settings), [Settings files](/en/settings#settings-files) |

21| [Decide what to enforce](#decide-what-to-enforce) | Which tools, commands, and integrations are allowed | [Permissions](/en/permissions), [Sandboxing](/en/sandboxing) |

22| [Set up usage visibility](#set-up-usage-visibility) | How you track spend and adoption | [Analytics](/en/analytics), [Monitoring](/en/monitoring-usage), [Costs](/en/costs) |

23| [Review data handling](#review-data-handling) | Data retention and compliance posture | [Data usage](/en/data-usage), [Security](/en/security) |

24 

25## Choose your API provider

26 

27Claude Code connects to Claude through one of several API providers. Your choice affects billing, authentication, and which compliance posture you inherit.

28 

29| Provider | Choose this when |

30| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ |

31| Claude for Teams / Enterprise | You want Claude Code and claude.ai under one per-seat subscription with no infrastructure to run. This is the default recommendation. |

32| Claude Console | You're API-first or want pay-as-you-go billing |

33| Amazon Bedrock | You want to inherit existing AWS compliance controls and billing |

34| Google Vertex AI | You want to inherit existing GCP compliance controls and billing |

35| Microsoft Foundry | You want to inherit existing Azure compliance controls and billing |

36 

37For the full provider comparison covering authentication, regions, and feature parity, see the [enterprise deployment overview](/en/third-party-integrations). Each provider's auth setup is in [Authentication](/en/authentication).

38 

39Proxy and firewall requirements in [Network configuration](/en/network-config) apply regardless of provider. If you want a single endpoint in front of multiple providers or centralized request logging, see [LLM gateway](/en/llm-gateway).

40 

41## Decide how settings reach devices

42 

43Managed settings define policy that takes precedence over local developer configuration. Claude Code looks for them in four places and uses the first one it finds on a given device.

44 

45| Mechanism | Delivery | Priority | Platforms |

46| :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | :------------- |

47| Server-managed | Claude.ai admin console | Highest | All |

48| plist / registry policy | macOS: `com.anthropic.claudecode` plist<br />Windows: `HKLM\SOFTWARE\Policies\ClaudeCode` | High | macOS, Windows |

49| File-based managed | macOS: `/Library/Application Support/ClaudeCode/managed-settings.json`<br />Linux and WSL: `/etc/claude-code/managed-settings.json`<br />Windows: `C:\Program Files\ClaudeCode\managed-settings.json` | Medium | All |

50| Windows user registry | `HKCU\SOFTWARE\Policies\ClaudeCode` | Lowest | Windows only |

51 

52Server-managed settings reach devices at authentication time and refresh hourly during active sessions, with no endpoint infrastructure. They require a Claude for Teams or Enterprise plan, so deployments on other providers need one of the file-based or OS-level mechanisms instead.

53 

54If your organization mixes providers, configure [server-managed settings](/en/server-managed-settings) for Claude.ai users plus a [file-based or plist/registry fallback](/en/settings#settings-files) so other users still receive managed policy.

55 

56The plist and HKLM registry locations work with any provider and resist tampering because they require admin privileges to write. The Windows user registry at HKCU is writable without elevation, so treat it as a convenience default rather than an enforcement channel.

57 

58By default WSL reads only the Linux file path at `/etc/claude-code`. To extend your Windows registry and `C:\Program Files\ClaudeCode` policy to WSL on the same machine, set [`wslInheritsWindowsSettings: true`](/en/settings#available-settings) in either of those admin-only Windows sources.

59 

60Whichever mechanism you choose, managed values take precedence over user and project settings. Array settings such as `permissions.allow` and `permissions.deny` merge entries from all sources, so developers can extend managed lists but not remove from them.

61 

62See [Server-managed settings](/en/server-managed-settings) and [Settings files and precedence](/en/settings#settings-files).

63 

64## Decide what to enforce

65 

66Managed settings can lock down tools, sandbox execution, restrict MCP servers and plugin sources, and control which hooks run. Each row is a control surface with the setting keys that drive it.

67 

68| Control | What it does | Key settings |

69| :------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------- | :---------------------------------------------------------------------------- |

70| [Permission rules](/en/permissions) | Allow, ask, or deny specific tools and commands | `permissions.allow`, `permissions.deny` |

71| [Permission lockdown](/en/permissions#managed-only-settings) | Only managed permission rules apply; disable `--dangerously-skip-permissions` | `allowManagedPermissionRulesOnly`, `permissions.disableBypassPermissionsMode` |

72| [Sandboxing](/en/sandboxing) | OS-level filesystem and network isolation with domain allowlists | `sandbox.enabled`, `sandbox.network.allowedDomains` |

73| [Managed policy CLAUDE.md](/en/memory#deploy-organization-wide-claude-md) | Org-wide instructions loaded in every session, cannot be excluded | File at the managed policy path |

74| [MCP server control](/en/mcp#managed-mcp-configuration) | Restrict which MCP servers users can add or connect to | `allowedMcpServers`, `deniedMcpServers`, `allowManagedMcpServersOnly` |

75| [Plugin marketplace control](/en/plugin-marketplaces#managed-marketplace-restrictions) | Restrict which marketplace sources users can add and install from | `strictKnownMarketplaces`, `blockedMarketplaces` |

76| [Hook restrictions](/en/settings#hook-configuration) | Only managed hooks load; restrict HTTP hook URLs | `allowManagedHooksOnly`, `allowedHttpHookUrls` |

77| [Version floor](/en/settings) | Prevent auto-update from installing below an org-wide minimum | `minimumVersion` |

78 

79Permission rules and sandboxing cover different layers. Denying WebFetch blocks Claude's fetch tool, but if Bash is allowed, `curl` and `wget` can still reach any URL. Sandboxing closes that gap with a network domain allowlist enforced at the OS level.

80 

81For the threat model these controls defend against, see [Security](/en/security).

82 

83## Set up usage visibility

84 

85Choose monitoring based on what you need to report on.

86 

87| Capability | What you get | Availability | Where to start |

88| :------------------ | :--------------------------------------------------- | :------------- | :--------------------------------------- |

89| Usage monitoring | OpenTelemetry export of sessions, tools, and tokens | All providers | [Monitoring usage](/en/monitoring-usage) |

90| Analytics dashboard | Per-user metrics, contribution tracking, leaderboard | Anthropic only | [Analytics](/en/analytics) |

91| Cost tracking | Spend limits, rate limits, and usage attribution | Anthropic only | [Costs](/en/costs) |

92 

93Cloud providers expose spend through AWS Cost Explorer, GCP Billing, or Azure Cost Management. Claude for Teams and Enterprise plans include a usage dashboard at [claude.ai/analytics/claude-code](https://claude.ai/analytics/claude-code).

94 

95## Review data handling

96 

97On Team, Enterprise, Claude API, and cloud provider plans, Anthropic does not train models on your code or prompts. Your API provider determines retention and compliance posture.

98 

99| Topic | What to know | Where to start |

100| :------------------------ | :------------------------------------------------------------------------------ | :--------------------------------------------- |

101| Data usage policy | What Anthropic collects, how long it's retained, what's never used for training | [Data usage](/en/data-usage) |

102| Zero Data Retention (ZDR) | Nothing stored after the request completes. Available on Claude for Enterprise | [Zero data retention](/en/zero-data-retention) |

103| Security architecture | Network model, encryption, authentication, audit trail | [Security](/en/security) |

104 

105If you need request-level audit logging or to route traffic by data sensitivity, place an [LLM gateway](/en/llm-gateway) between developers and your provider. For regulatory requirements and certifications, see [Legal and compliance](/en/legal-and-compliance).

106 

107## Verify and onboard

108 

109After configuring managed settings, have a developer run `/status` inside Claude Code. The output includes a line beginning with `Enterprise managed settings` followed by the source in parentheses, one of `(remote)`, `(plist)`, `(HKLM)`, `(HKCU)`, or `(file)`. See [Verify active settings](/en/settings#verify-active-settings).

110 

111Share these resources to help developers get started:

112 

113* [Quickstart](/en/quickstart): first-session walkthrough from install to working with a project

114* [Common workflows](/en/common-workflows): patterns for everyday tasks like code review, refactoring, and debugging

115* [Claude 101](https://anthropic.skilljar.com/claude-101) and [Claude Code in Action](https://anthropic.skilljar.com/claude-code-in-action): self-paced Anthropic Academy courses

116 

117For login issues, point developers to [authentication troubleshooting](/en/troubleshooting#authentication-issues). The most common fixes are:

118 

119* Run `/logout` then `/login` to switch accounts

120* Run `claude update` if the enterprise auth option is missing

121* Restart the terminal after updating

122 

123If a developer sees "You haven't been added to your organization yet," their seat doesn't include Claude Code access and needs to be updated in the admin console.

124 

125## Next steps

126 

127With provider and delivery mechanism chosen, move on to detailed configuration:

128 

129* [Server-managed settings](/en/server-managed-settings): deliver managed policy from the Claude admin console

130* [Settings reference](/en/settings): every setting key, file location, and precedence rule

131* [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), [Microsoft Foundry](/en/microsoft-foundry): provider-specific deployment

132* [Claude Enterprise Administrator Guide](https://claude.com/resources/tutorials/claude-enterprise-administrator-guide): SSO, SCIM, seat management, and rollout playbook

agent-sdk/agent-loop.md +395 −0 added

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# How the agent loop works

6 

7> Understand the message lifecycle, tool execution, context window, and architecture that power your SDK agents.

8 

9The Agent SDK lets you embed Claude Code's autonomous agent loop in your own applications. The SDK is a standalone package that gives you programmatic control over tools, permissions, cost limits, and output. You don't need the Claude Code CLI installed to use it.

10 

11When you start an agent, the SDK runs the same [execution loop that powers Claude Code](/en/how-claude-code-works#the-agentic-loop): Claude evaluates your prompt, calls tools to take action, receives the results, and repeats until the task is complete. This page explains what happens inside that loop so you can build, debug, and optimize your agents effectively.

12 

13## The loop at a glance

14 

15Every agent session follows the same cycle:

16 

17<img src="https://mintcdn.com/claude-code/gvy2DIUELtNA8qD3/images/agent-loop-diagram.svg?fit=max&auto=format&n=gvy2DIUELtNA8qD3&q=85&s=192e1bd6c8a2950a16e5ee0b94e27e26" alt="Agent loop: prompt enters, Claude evaluates, branches to tool calls or final answer" width="680" height="150" data-path="images/agent-loop-diagram.svg" />

18 

191. **Receive prompt.** Claude receives your prompt, along with the system prompt, tool definitions, and conversation history. The SDK yields a [`SystemMessage`](#message-types) with subtype `"init"` containing session metadata.

202. **Evaluate and respond.** Claude evaluates the current state and determines how to proceed. It may respond with text, request one or more tool calls, or both. The SDK yields an [`AssistantMessage`](#message-types) containing the text and any tool call requests.

213. **Execute tools.** The SDK runs each requested tool and collects the results. Each set of tool results feeds back to Claude for the next decision. You can use [hooks](/en/agent-sdk/hooks) to intercept, modify, or block tool calls before they run.

224. **Repeat.** Steps 2 and 3 repeat as a cycle. Each full cycle is one turn. Claude continues calling tools and processing results until it produces a response with no tool calls.

235. **Return result.** The SDK yields a final [`AssistantMessage`](#message-types) with the text response (no tool calls), followed by a [`ResultMessage`](#message-types) with the final text, token usage, cost, and session ID.

24 

25A quick question ("what files are here?") might take one or two turns of calling `Glob` and responding with the results. A complex task ("refactor the auth module and update the tests") can chain dozens of tool calls across many turns, reading files, editing code, and running tests, with Claude adjusting its approach based on each result.

26 

27## Turns and messages

28 

29A turn is one round trip inside the loop: Claude produces output that includes tool calls, the SDK executes those tools, and the results feed back to Claude automatically. This happens without yielding control back to your code. Turns continue until Claude produces output with no tool calls, at which point the loop ends and the final result is delivered.

30 

31Consider what a full session might look like for the prompt "Fix the failing tests in auth.ts".

32 

33First, the SDK sends your prompt to Claude and yields a [`SystemMessage`](#message-types) with the session metadata. Then the loop begins:

34 

351. **Turn 1:** Claude calls `Bash` to run `npm test`. The SDK yields an [`AssistantMessage`](#message-types) with the tool call, executes the command, then yields a [`UserMessage`](#message-types) with the output (three failures).

362. **Turn 2:** Claude calls `Read` on `auth.ts` and `auth.test.ts`. The SDK returns the file contents and yields an `AssistantMessage`.

373. **Turn 3:** Claude calls `Edit` to fix `auth.ts`, then calls `Bash` to re-run `npm test`. All three tests pass. The SDK yields an `AssistantMessage`.

384. **Final turn:** Claude produces a text-only response with no tool calls: "Fixed the auth bug, all three tests pass now." The SDK yields a final `AssistantMessage` with this text, then a [`ResultMessage`](#message-types) with the same text plus cost and usage.

39 

40That was four turns: three with tool calls, one final text-only response.

41 

42You can cap the loop with `max_turns` / `maxTurns`, which counts tool-use turns only. For example, `max_turns=2` in the loop above would have stopped before the edit step. You can also use `max_budget_usd` / `maxBudgetUsd` to cap turns based on a spend threshold.

43 

44Without limits, the loop runs until Claude finishes on its own, which is fine for well-scoped tasks but can run long on open-ended prompts ("improve this codebase"). Setting a budget is a good default for production agents. See [Turns and budget](#turns-and-budget) below for the option reference.

45 

46## Message types

47 

48As the loop runs, the SDK yields a stream of messages. Each message carries a type that tells you what stage of the loop it came from. The five core types are:

49 

50* **`SystemMessage`:** session lifecycle events. The `subtype` field distinguishes them: `"init"` is the first message (session metadata), and `"compact_boundary"` fires after [compaction](#automatic-compaction). In TypeScript, the compact boundary is its own [`SDKCompactBoundaryMessage`](/en/agent-sdk/typescript#sdk-compact-boundary-message) type rather than a subtype of `SDKSystemMessage`.

51* **`AssistantMessage`:** emitted after each Claude response, including the final text-only one. Contains text content blocks and tool call blocks from that turn.

52* **`UserMessage`:** emitted after each tool execution with the tool result content sent back to Claude. Also emitted for any user inputs you stream mid-loop.

53* **`StreamEvent`:** only emitted when partial messages are enabled. Contains raw API streaming events (text deltas, tool input chunks). See [Stream responses](/en/agent-sdk/streaming-output).

54* **`ResultMessage`:** marks the end of the agent loop. Contains the final text result, token usage, cost, and session ID. Check the `subtype` field to determine whether the task succeeded or hit a limit. A small number of trailing system events, such as `prompt_suggestion`, can arrive after it, so iterate the stream to completion rather than breaking on the result. See [Handle the result](#handle-the-result).

55 

56These five types cover the full agent loop lifecycle in both SDKs. The TypeScript SDK also yields additional observability events (hook events, tool progress, rate limits, task notifications) that provide extra detail but are not required to drive the loop. See the [Python message types reference](/en/agent-sdk/python#message-types) and [TypeScript message types reference](/en/agent-sdk/typescript#message-types) for the complete lists.

57 

58### Handle messages

59 

60Which messages you handle depends on what you're building:

61 

62* **Final results only:** handle `ResultMessage` to get the output, cost, and whether the task succeeded or hit a limit.

63* **Progress updates:** handle `AssistantMessage` to see what Claude is doing each turn, including which tools it called.

64* **Live streaming:** enable partial messages (`include_partial_messages` in Python, `includePartialMessages` in TypeScript) to get `StreamEvent` messages in real time. See [Stream responses in real-time](/en/agent-sdk/streaming-output).

65 

66How you check message types depends on the SDK:

67 

68* **Python:** check message types with `isinstance()` against classes imported from `claude_agent_sdk` (for example, `isinstance(message, ResultMessage)`).

69* **TypeScript:** check the `type` string field (for example, `message.type === "result"`). `AssistantMessage` and `UserMessage` wrap the raw API message in a `.message` field, so content blocks are at `message.message.content`, not `message.content`.

70 

71<Accordion title="Example: Check message types and handle results">

72 <CodeGroup>

73 ```python Python theme={null}

74 from claude_agent_sdk import query, AssistantMessage, ResultMessage

75 

76 async for message in query(prompt="Summarize this project"):

77 if isinstance(message, AssistantMessage):

78 print(f"Turn completed: {len(message.content)} content blocks")

79 if isinstance(message, ResultMessage):

80 if message.subtype == "success":

81 print(message.result)

82 else:

83 print(f"Stopped: {message.subtype}")

84 ```

85 

86 ```typescript TypeScript theme={null}

87 import { query } from "@anthropic-ai/claude-agent-sdk";

88 

89 for await (const message of query({ prompt: "Summarize this project" })) {

90 if (message.type === "assistant") {

91 console.log(`Turn completed: ${message.message.content.length} content blocks`);

92 }

93 if (message.type === "result") {

94 if (message.subtype === "success") {

95 console.log(message.result);

96 } else {

97 console.log(`Stopped: ${message.subtype}`);

98 }

99 }

100 }

101 ```

102 </CodeGroup>

103</Accordion>

104 

105## Tool execution

106 

107Tools give your agent the ability to take action. Without tools, Claude can only respond with text. With tools, Claude can read files, run commands, search code, and interact with external services.

108 

109### Built-in tools

110 

111The SDK includes the same tools that power Claude Code:

112 

113| Category | Tools | What they do |

114| :------------------ | :----------------------------------------------- | :-------------------------------------------------------------------------- |

115| **File operations** | `Read`, `Edit`, `Write` | Read, modify, and create files |

116| **Search** | `Glob`, `Grep` | Find files by pattern, search content with regex |

117| **Execution** | `Bash` | Run shell commands, scripts, git operations |

118| **Web** | `WebSearch`, `WebFetch` | Search the web, fetch and parse pages |

119| **Discovery** | `ToolSearch` | Dynamically find and load tools on-demand instead of preloading all of them |

120| **Orchestration** | `Agent`, `Skill`, `AskUserQuestion`, `TodoWrite` | Spawn subagents, invoke skills, ask the user, track tasks |

121 

122Beyond built-in tools, you can:

123 

124* **Connect external services** with [MCP servers](/en/agent-sdk/mcp) (databases, browsers, APIs)

125* **Define custom tools** with [custom tool handlers](/en/agent-sdk/custom-tools)

126* **Load project skills** via [setting sources](/en/agent-sdk/claude-code-features) for reusable workflows

127 

128### Tool permissions

129 

130Claude determines which tools to call based on the task, but you control whether those calls are allowed to execute. You can auto-approve specific tools, block others entirely, or require approval for everything. Three options work together to determine what runs:

131 

132* **`allowed_tools` / `allowedTools`** auto-approves listed tools. A read-only agent with `["Read", "Glob", "Grep"]` in its allowed tools list runs those tools without prompting. Tools not listed are still available but require permission.

133* **`disallowed_tools` / `disallowedTools`** blocks listed tools, regardless of other settings. See [Permissions](/en/agent-sdk/permissions) for the order that rules are checked before a tool runs.

134* **`permission_mode` / `permissionMode`** controls what happens to tools that aren't covered by allow or deny rules. See [Permission mode](#permission-mode) for available modes.

135 

136You can also scope individual tools with rules like `"Bash(npm *)"` to allow only specific commands. See [Permissions](/en/agent-sdk/permissions) for the full rule syntax.

137 

138When a tool is denied, Claude receives a rejection message as the tool result and typically attempts a different approach or reports that it couldn't proceed.

139 

140### Parallel tool execution

141 

142When Claude requests multiple tool calls in a single turn, both SDKs can run them concurrently or sequentially depending on the tool. Read-only tools (like `Read`, `Glob`, `Grep`, and MCP tools marked as read-only) can run concurrently. Tools that modify state (like `Edit`, `Write`, and `Bash`) run sequentially to avoid conflicts.

143 

144Custom tools default to sequential execution. To enable parallel execution for a custom tool, mark it as read-only in its annotations: `readOnly` in [TypeScript](/en/agent-sdk/typescript#tool) or `readOnlyHint` in [Python](/en/agent-sdk/python#tool).

145 

146## Control how the loop runs

147 

148You can limit how many turns the loop takes, how much it costs, how deeply Claude reasons, and whether tools require approval before running. All of these are fields on [`ClaudeAgentOptions`](/en/agent-sdk/python#claude-agent-options) (Python) / [`Options`](/en/agent-sdk/typescript#options) (TypeScript).

149 

150### Turns and budget

151 

152| Option | What it controls | Default |

153| :--------------------------------------------- | :--------------------------- | :------- |

154| Max turns (`max_turns` / `maxTurns`) | Maximum tool-use round trips | No limit |

155| Max budget (`max_budget_usd` / `maxBudgetUsd`) | Maximum cost before stopping | No limit |

156 

157When either limit is hit, the SDK returns a `ResultMessage` with a corresponding error subtype (`error_max_turns` or `error_max_budget_usd`). See [Handle the result](#handle-the-result) for how to check these subtypes and [`ClaudeAgentOptions`](/en/agent-sdk/python#claude-agent-options) / [`Options`](/en/agent-sdk/typescript#options) for syntax.

158 

159### Effort level

160 

161The `effort` option controls how much reasoning Claude applies. Lower effort levels use fewer tokens per turn and reduce cost. Not all models support the effort parameter. See [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) for which models support it.

162 

163| Level | Behavior | Good for |

164| :--------- | :-------------------------------- | :------------------------------------------------ |

165| `"low"` | Minimal reasoning, fast responses | File lookups, listing directories |

166| `"medium"` | Balanced reasoning | Routine edits, standard tasks |

167| `"high"` | Thorough analysis | Refactors, debugging |

168| `"xhigh"` | Extended reasoning depth | Coding and agentic tasks; recommended on Opus 4.7 |

169| `"max"` | Maximum reasoning depth | Multi-step problems requiring deep analysis |

170 

171If you don't set `effort`, the Python SDK leaves the parameter unset and defers to the model's default behavior. The TypeScript SDK defaults to `"high"`.

172 

173<Note>

174 `effort` trades latency and token cost for reasoning depth within each response. [Extended thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking) is a separate feature that produces visible chain-of-thought blocks in the output. They are independent: you can set `effort: "low"` with extended thinking enabled, or `effort: "max"` without it.

175</Note>

176 

177Use lower effort for agents doing simple, well-scoped tasks (like listing files or running a single grep) to reduce cost and latency. `effort` is set at the top-level `query()` options, not per-subagent.

178 

179### Permission mode

180 

181The permission mode option (`permission_mode` in Python, `permissionMode` in TypeScript) controls whether the agent asks for approval before using tools:

182 

183| Mode | Behavior |

184| :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

185| `"default"` | Tools not covered by allow rules trigger your approval callback; no callback means deny |

186| `"acceptEdits"` | Auto-approves file edits and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.); other Bash commands follow default rules |

187| `"plan"` | No tool execution; Claude produces a plan for review |

188| `"dontAsk"` | Never prompts. Tools pre-approved by [permission rules](/en/settings#permission-settings) run, everything else is denied |

189| `"auto"` (TypeScript only) | Uses a model classifier to approve or deny each tool call. See [Auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) for availability and behavior |

190| `"bypassPermissions"` | Runs all allowed tools without asking. Cannot be used when running as root on Unix. Use only in isolated environments where the agent's actions cannot affect systems you care about |

191 

192For interactive applications, use `"default"` with a tool approval callback to surface approval prompts. For autonomous agents on a dev machine, `"acceptEdits"` auto-approves file edits and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.) while still gating other `Bash` commands behind allow rules. Reserve `"bypassPermissions"` for CI, containers, or other isolated environments. See [Permissions](/en/agent-sdk/permissions) for full details.

193 

194### Model

195 

196If you don't set `model`, the SDK uses Claude Code's default, which depends on your authentication method and subscription. Set it explicitly (for example, `model="claude-sonnet-4-6"`) to pin a specific model or to use a smaller model for faster, cheaper agents. See [models](https://platform.claude.com/docs/en/about-claude/models) for available IDs.

197 

198## The context window

199 

200The context window is the total amount of information available to Claude during a session. It does not reset between turns within a session. Everything accumulates: the system prompt, tool definitions, conversation history, tool inputs, and tool outputs. Content that stays the same across turns (system prompt, tool definitions, CLAUDE.md) is automatically [prompt cached](https://platform.claude.com/docs/en/build-with-claude/prompt-caching), which reduces cost and latency for repeated prefixes.

201 

202### What consumes context

203 

204Here's how each component affects context in the SDK:

205 

206| Source | When it loads | Impact |

207| :----------------------- | :------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------- |

208| **System prompt** | Every request | Small fixed cost, always present |

209| **CLAUDE.md files** | Session start, via [`settingSources`](/en/agent-sdk/claude-code-features) | Full content in every request (but prompt-cached, so only the first request pays full cost) |

210| **Tool definitions** | Every request | Each tool adds its schema; use [MCP tool search](/en/agent-sdk/mcp#mcp-tool-search) to load tools on-demand instead of all at once |

211| **Conversation history** | Accumulates over turns | Grows with each turn: prompts, responses, tool inputs, tool outputs |

212| **Skill descriptions** | Session start, via setting sources | Short summaries; full content loads only when invoked |

213 

214Large tool outputs consume significant context. Reading a big file or running a command with verbose output can use thousands of tokens in a single turn. Context accumulates across turns, so longer sessions with many tool calls build up significantly more context than short ones.

215 

216### Automatic compaction

217 

218When the context window approaches its limit, the SDK automatically compacts the conversation: it summarizes older history to free space, keeping your most recent exchanges and key decisions intact. The SDK emits a message with `type: "system"` and `subtype: "compact_boundary"` in the stream when this happens (in Python this is a `SystemMessage`; in TypeScript it is a separate `SDKCompactBoundaryMessage` type).

219 

220Compaction replaces older messages with a summary, so specific instructions from early in the conversation may not be preserved. Persistent rules belong in CLAUDE.md (loaded via [`settingSources`](/en/agent-sdk/claude-code-features)) rather than in the initial prompt, because CLAUDE.md content is re-injected on every request.

221 

222You can customize compaction behavior in several ways:

223 

224* **Summarization instructions in CLAUDE.md:** The compactor reads your CLAUDE.md like any other context, so you can include a section telling it what to preserve when summarizing. The section header is free-form (not a magic string); the compactor matches on intent.

225* **`PreCompact` hook:** Run custom logic before compaction occurs, for example to archive the full transcript. The hook receives a `trigger` field (`manual` or `auto`). See [hooks](/en/agent-sdk/hooks).

226* **Manual compaction:** Send `/compact` as a prompt string to trigger compaction on demand. (Slash commands sent this way are SDK inputs, not CLI-only shortcuts. See [slash commands in the SDK](/en/agent-sdk/slash-commands).)

227 

228<Accordion title="Example: Summarization instructions in CLAUDE.md">

229 Add a section to your project's CLAUDE.md telling the compactor what to preserve. The header name isn't special; use any clear label.

230 

231 ```markdown CLAUDE.md theme={null}

232 # Summary instructions

233 

234 When summarizing this conversation, always preserve:

235 - The current task objective and acceptance criteria

236 - File paths that have been read or modified

237 - Test results and error messages

238 - Decisions made and the reasoning behind them

239 ```

240</Accordion>

241 

242### Keep context efficient

243 

244A few strategies for long-running agents:

245 

246* **Use subagents for subtasks.** Each subagent starts with a fresh conversation (no prior message history, though it does load its own system prompt and project-level context like CLAUDE.md). It does not see the parent's turns, and only its final response returns to the parent as a tool result. The main agent's context grows by that summary, not by the full subtask transcript. See [What subagents inherit](/en/agent-sdk/subagents#what-subagents-inherit) for details.

247* **Be selective with tools.** Every tool definition takes context space. Use the `tools` field on [`AgentDefinition`](/en/agent-sdk/subagents#agent-definition-configuration) to scope subagents to the minimum set they need, and use [MCP tool search](/en/agent-sdk/mcp#mcp-tool-search) to load tools on demand instead of preloading all of them.

248* **Watch MCP server costs.** Each MCP server adds all its tool schemas to every request. A few servers with many tools can consume significant context before the agent does any work. The `ToolSearch` tool can help by loading tools on-demand instead of preloading all of them. See [MCP tool search](/en/agent-sdk/mcp#mcp-tool-search) for configuration.

249* **Use lower effort for routine tasks.** Set [effort](#effort-level) to `"low"` for agents that only need to read files or list directories. This reduces token usage and cost.

250 

251For a detailed breakdown of per-feature context costs, see [Understand context costs](/en/features-overview#understand-context-costs).

252 

253## Sessions and continuity

254 

255Each interaction with the SDK creates or continues a session. Capture the session ID from `ResultMessage.session_id` (available in both SDKs) to resume later. The TypeScript SDK also exposes it as a direct field on the init `SystemMessage`; in Python it's nested in `SystemMessage.data`.

256 

257When you resume, the full context from previous turns is restored: files that were read, analysis that was performed, and actions that were taken. You can also fork a session to branch into a different approach without modifying the original.

258 

259See [Session management](/en/agent-sdk/sessions) for the full guide on resume, continue, and fork patterns.

260 

261<Note>

262 In Python, `ClaudeSDKClient` handles session IDs automatically across multiple calls. See the [Python SDK reference](/en/agent-sdk/python#choosing-between-query-and-claude-sdk-client) for details.

263</Note>

264 

265## Handle the result

266 

267When the loop ends, the `ResultMessage` tells you what happened and gives you the output. The `subtype` field (available in both SDKs) is the primary way to check termination state.

268 

269| Result subtype | What happened | `result` field available? |

270| :------------------------------------ | :------------------------------------------------------------------------------- | :-----------------------: |

271| `success` | Claude finished the task normally | Yes |

272| `error_max_turns` | Hit the `maxTurns` limit before finishing | No |

273| `error_max_budget_usd` | Hit the `maxBudgetUsd` limit before finishing | No |

274| `error_during_execution` | An error interrupted the loop (for example, an API failure or cancelled request) | No |

275| `error_max_structured_output_retries` | Structured output validation failed after the configured retry limit | No |

276 

277The `result` field (the final text output) is only present on the `success` variant, so always check the subtype before reading it. All result subtypes carry `total_cost_usd`, `usage`, `num_turns`, and `session_id` so you can track cost and resume even after errors. In Python, `total_cost_usd` and `usage` are typed as optional and may be `None` on some error paths, so guard before formatting them. See [Tracking costs and usage](/en/agent-sdk/cost-tracking) for details on interpreting the `usage` fields.

278 

279The result also includes a `stop_reason` field (`string | null` in TypeScript, `str | None` in Python) indicating why the model stopped generating on its final turn. Common values are `end_turn` (model finished normally), `max_tokens` (hit the output token limit), and `refusal` (the model declined the request). On error result subtypes, `stop_reason` carries the value from the last assistant response before the loop ended. To detect refusals, check `stop_reason === "refusal"` (TypeScript) or `stop_reason == "refusal"` (Python). See [`SDKResultMessage`](/en/agent-sdk/typescript#sdk-result-message) (TypeScript) or [`ResultMessage`](/en/agent-sdk/python#result-message) (Python) for the full type.

280 

281## Hooks

282 

283[Hooks](/en/agent-sdk/hooks) are callbacks that fire at specific points in the loop: before a tool runs, after it returns, when the agent finishes, and so on. Some commonly used hooks are:

284 

285| Hook | When it fires | Common uses |

286| :------------------------------- | :---------------------------------- | :----------------------------------------- |

287| `PreToolUse` | Before a tool executes | Validate inputs, block dangerous commands |

288| `PostToolUse` | After a tool returns | Audit outputs, trigger side effects |

289| `UserPromptSubmit` | When a prompt is sent | Inject additional context into prompts |

290| `Stop` | When the agent finishes | Validate the result, save session state |

291| `SubagentStart` / `SubagentStop` | When a subagent spawns or completes | Track and aggregate parallel task results |

292| `PreCompact` | Before context compaction | Archive full transcript before summarizing |

293 

294Hooks run in your application process, not inside the agent's context window, so they don't consume context. Hooks can also short-circuit the loop: a `PreToolUse` hook that rejects a tool call prevents it from executing, and Claude receives the rejection message instead.

295 

296Both SDKs support all the events above. The TypeScript SDK includes additional events that Python does not yet support. See [Control execution with hooks](/en/agent-sdk/hooks) for the complete event list, per-SDK availability, and the full callback API.

297 

298## Put it all together

299 

300This example combines the key concepts from this page into a single agent that fixes failing tests. It configures the agent with allowed tools (auto-approved so the agent runs autonomously), project settings, and safety limits on turns and reasoning effort. As the loop runs, it captures the session ID for potential resumption, handles the final result, and prints the total cost.

301 

302<CodeGroup>

303 ```python Python theme={null}

304 import asyncio

305 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

306 

307 

308 async def run_agent():

309 session_id = None

310 

311 async for message in query(

312 prompt="Find and fix the bug causing test failures in the auth module",

313 options=ClaudeAgentOptions(

314 allowed_tools=[

315 "Read",

316 "Edit",

317 "Bash",

318 "Glob",

319 "Grep",

320 ], # Listing tools here auto-approves them (no prompting)

321 setting_sources=[

322 "project"

323 ], # Load CLAUDE.md, skills, hooks from current directory

324 max_turns=30, # Prevent runaway sessions

325 effort="high", # Thorough reasoning for complex debugging

326 ),

327 ):

328 # Handle the final result

329 if isinstance(message, ResultMessage):

330 session_id = message.session_id # Save for potential resumption

331 

332 if message.subtype == "success":

333 print(f"Done: {message.result}")

334 elif message.subtype == "error_max_turns":

335 # Agent ran out of turns. Resume with a higher limit.

336 print(f"Hit turn limit. Resume session {session_id} to continue.")

337 elif message.subtype == "error_max_budget_usd":

338 print("Hit budget limit.")

339 else:

340 print(f"Stopped: {message.subtype}")

341 if message.total_cost_usd is not None:

342 print(f"Cost: ${message.total_cost_usd:.4f}")

343 

344 

345 asyncio.run(run_agent())

346 ```

347 

348 ```typescript TypeScript theme={null}

349 import { query } from "@anthropic-ai/claude-agent-sdk";

350 

351 let sessionId: string | undefined;

352 

353 for await (const message of query({

354 prompt: "Find and fix the bug causing test failures in the auth module",

355 options: {

356 allowedTools: ["Read", "Edit", "Bash", "Glob", "Grep"], // Listing tools here auto-approves them (no prompting)

357 settingSources: ["project"], // Load CLAUDE.md, skills, hooks from current directory

358 maxTurns: 30, // Prevent runaway sessions

359 effort: "high" // Thorough reasoning for complex debugging

360 }

361 })) {

362 // Save the session ID to resume later if needed

363 if (message.type === "system" && message.subtype === "init") {

364 sessionId = message.session_id;

365 }

366 

367 // Handle the final result

368 if (message.type === "result") {

369 if (message.subtype === "success") {

370 console.log(`Done: ${message.result}`);

371 } else if (message.subtype === "error_max_turns") {

372 // Agent ran out of turns. Resume with a higher limit.

373 console.log(`Hit turn limit. Resume session ${sessionId} to continue.`);

374 } else if (message.subtype === "error_max_budget_usd") {

375 console.log("Hit budget limit.");

376 } else {

377 console.log(`Stopped: ${message.subtype}`);

378 }

379 console.log(`Cost: $${message.total_cost_usd.toFixed(4)}`);

380 }

381 }

382 ```

383</CodeGroup>

384 

385## Next steps

386 

387Now that you understand the loop, here's where to go depending on what you're building:

388 

389* **Haven't run an agent yet?** Start with the [quickstart](/en/agent-sdk/quickstart) to get the SDK installed and see a full example running end to end.

390* **Ready to hook into your project?** [Load CLAUDE.md, skills, and filesystem hooks](/en/agent-sdk/claude-code-features) so the agent follows your project conventions automatically.

391* **Building an interactive UI?** Enable [streaming](/en/agent-sdk/streaming-output) to show live text and tool calls as the loop runs.

392* **Need tighter control over what the agent can do?** Lock down tool access with [permissions](/en/agent-sdk/permissions), and use [hooks](/en/agent-sdk/hooks) to audit, block, or transform tool calls before they execute.

393* **Running long or expensive tasks?** Offload isolated work to [subagents](/en/agent-sdk/subagents) to keep your main context lean.

394 

395For the broader conceptual picture of the agentic loop (not SDK-specific), see [How Claude Code works](/en/how-claude-code-works).

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# Use Claude Code features in the SDK

6 

7> Load project instructions, skills, hooks, and other Claude Code features into your SDK agents.

8 

9The Agent SDK is built on the same foundation as Claude Code, which means your SDK agents have access to the same filesystem-based features: project instructions (`CLAUDE.md` and rules), skills, hooks, and more.

10 

11When you omit `settingSources`, `query()` reads the same filesystem settings as the Claude Code CLI: user, project, and local settings, CLAUDE.md files, and `.claude/` skills, agents, and commands. To run without these, pass `settingSources: []`, which limits the agent to what you configure programmatically. Managed policy settings and the global `~/.claude.json` config are read regardless of this option. See [What settingSources does not control](#what-settingsources-does-not-control).

12 

13For a conceptual overview of what each feature does and when to use it, see [Extend Claude Code](/en/features-overview).

14 

15## Control filesystem settings with settingSources

16 

17The setting sources option ([`setting_sources`](/en/agent-sdk/python#claude-agent-options) in Python, [`settingSources`](/en/agent-sdk/typescript#setting-source) in TypeScript) controls which filesystem-based settings the SDK loads. Pass an explicit list to opt in to specific sources, or pass an empty array to disable user, project, and local settings.

18 

19This example loads both user-level and project-level settings by setting `settingSources` to `["user", "project"]`:

20 

21<CodeGroup>

22 ```python Python theme={null}

23 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage

24 

25 async for message in query(

26 prompt="Help me refactor the auth module",

27 options=ClaudeAgentOptions(

28 # "user" loads from ~/.claude/, "project" loads from ./.claude/ in cwd.

29 # Together they give the agent access to CLAUDE.md, skills, hooks, and

30 # permissions from both locations.

31 setting_sources=["user", "project"],

32 allowed_tools=["Read", "Edit", "Bash"],

33 ),

34 ):

35 if isinstance(message, AssistantMessage):

36 for block in message.content:

37 if hasattr(block, "text"):

38 print(block.text)

39 if isinstance(message, ResultMessage) and message.subtype == "success":

40 print(f"\nResult: {message.result}")

41 ```

42 

43 ```typescript TypeScript theme={null}

44 import { query } from "@anthropic-ai/claude-agent-sdk";

45 

46 for await (const message of query({

47 prompt: "Help me refactor the auth module",

48 options: {

49 // "user" loads from ~/.claude/, "project" loads from ./.claude/ in cwd.

50 // Together they give the agent access to CLAUDE.md, skills, hooks, and

51 // permissions from both locations.

52 settingSources: ["user", "project"],

53 allowedTools: ["Read", "Edit", "Bash"]

54 }

55 })) {

56 if (message.type === "assistant") {

57 for (const block of message.message.content) {

58 if (block.type === "text") console.log(block.text);

59 }

60 }

61 if (message.type === "result" && message.subtype === "success") {

62 console.log(`\nResult: ${message.result}`);

63 }

64 }

65 ```

66</CodeGroup>

67 

68Each source loads settings from a specific location, where `<cwd>` is the working directory you pass via the `cwd` option (or the process's current directory if unset). For the full type definition, see [`SettingSource`](/en/agent-sdk/typescript#setting-source) (TypeScript) or [`SettingSource`](/en/agent-sdk/python#setting-source) (Python).

69 

70| Source | What it loads | Location |

71| :---------- | :---------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- |

72| `"project"` | Project CLAUDE.md, `.claude/rules/*.md`, project skills, project hooks, project `settings.json` | `<cwd>/.claude/` and each parent directory up to the filesystem root (stopping when a `.claude/` is found or no more parents exist) |

73| `"user"` | User CLAUDE.md, `~/.claude/rules/*.md`, user skills, user settings | `~/.claude/` |

74| `"local"` | CLAUDE.local.md (gitignored), `.claude/settings.local.json` | `<cwd>/` |

75 

76Omitting `settingSources` is equivalent to `["user", "project", "local"]`.

77 

78The `cwd` option determines where the SDK looks for project settings. If neither `cwd` nor any of its parent directories contains a `.claude/` folder, project-level features won't load.

79 

80### What settingSources does not control

81 

82`settingSources` covers user, project, and local settings. A few inputs are read regardless of its value:

83 

84| Input | Behavior | To disable |

85| :---------------------------------------------------- | :--------------------------------------- | :------------------------------------------------------------------------------------------ |

86| Managed policy settings | Always loaded when present on the host | Remove the managed settings file |

87| `~/.claude.json` global config | Always read | Relocate with `CLAUDE_CONFIG_DIR` in `env` |

88| Auto memory at `~/.claude/projects/<project>/memory/` | Loaded by default into the system prompt | Set `autoMemoryEnabled: false` in settings, or `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` in `env` |

89 

90<Warning>

91 Do not rely on default `query()` options for multi-tenant isolation. Because the inputs above are read regardless of `settingSources`, an SDK process can pick up host-level configuration and per-directory memory. For multi-tenant deployments, run each tenant in its own filesystem and set `settingSources: []` plus `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` in `env`. See [Secure deployment](/en/agent-sdk/secure-deployment).

92</Warning>

93 

94## Project instructions (CLAUDE.md and rules)

95 

96`CLAUDE.md` files and `.claude/rules/*.md` files give your agent persistent context about your project: coding conventions, build commands, architecture decisions, and instructions. When `settingSources` includes `"project"` (as in the example above), the SDK loads these files into context at session start. The agent then follows your project conventions without you repeating them in every prompt.

97 

98### CLAUDE.md load locations

99 

100| Level | Location | When loaded |

101| :-------------------- | :--------------------------------------------- | :-------------------------------------------------------------------------------------------------- |

102| Project (root) | `<cwd>/CLAUDE.md` or `<cwd>/.claude/CLAUDE.md` | `settingSources` includes `"project"` |

103| Project rules | `<cwd>/.claude/rules/*.md` | `settingSources` includes `"project"` |

104| Project (parent dirs) | `CLAUDE.md` files in directories above `cwd` | `settingSources` includes `"project"`, loaded at session start |

105| Project (child dirs) | `CLAUDE.md` files in subdirectories of `cwd` | `settingSources` includes `"project"`, loaded on demand when the agent reads a file in that subtree |

106| Local (gitignored) | `<cwd>/CLAUDE.local.md` | `settingSources` includes `"local"` |

107| User | `~/.claude/CLAUDE.md` | `settingSources` includes `"user"` |

108| User rules | `~/.claude/rules/*.md` | `settingSources` includes `"user"` |

109 

110All levels are additive: if both project and user CLAUDE.md files exist, the agent sees both. There is no hard precedence rule between levels; if instructions conflict, the outcome depends on how Claude interprets them. Write non-conflicting rules, or state precedence explicitly in the more specific file ("These project instructions override any conflicting user-level defaults").

111 

112<Tip>

113 You can also inject context directly via `systemPrompt` without using CLAUDE.md files. See [Modify system prompts](/en/agent-sdk/modifying-system-prompts). Use CLAUDE.md when you want the same context shared between interactive Claude Code sessions and your SDK agents.

114</Tip>

115 

116For how to structure and organize CLAUDE.md content, see [Manage Claude's memory](/en/memory).

117 

118## Skills

119 

120Skills are markdown files that give your agent specialized knowledge and invocable workflows. Unlike `CLAUDE.md` (which loads every session), skills load on demand. The agent receives skill descriptions at startup and loads the full content when relevant.

121 

122Skills are discovered from the filesystem through `settingSources`. With default options, user and project skills load automatically. The `Skill` tool is enabled by default when you don't specify `allowedTools`. If you are using an `allowedTools` allowlist, include `"Skill"` explicitly.

123 

124<CodeGroup>

125 ```python Python theme={null}

126 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

127 

128 # Skills in .claude/skills/ are discovered automatically

129 # when settingSources includes "project"

130 async for message in query(

131 prompt="Review this PR using our code review checklist",

132 options=ClaudeAgentOptions(

133 setting_sources=["user", "project"],

134 allowed_tools=["Skill", "Read", "Grep", "Glob"],

135 ),

136 ):

137 if isinstance(message, ResultMessage) and message.subtype == "success":

138 print(message.result)

139 ```

140 

141 ```typescript TypeScript theme={null}

142 import { query } from "@anthropic-ai/claude-agent-sdk";

143 

144 // Skills in .claude/skills/ are discovered automatically

145 // when settingSources includes "project"

146 for await (const message of query({

147 prompt: "Review this PR using our code review checklist",

148 options: {

149 settingSources: ["user", "project"],

150 allowedTools: ["Skill", "Read", "Grep", "Glob"]

151 }

152 })) {

153 if (message.type === "result" && message.subtype === "success") {

154 console.log(message.result);

155 }

156 }

157 ```

158</CodeGroup>

159 

160<Note>

161 Skills must be created as filesystem artifacts (`.claude/skills/<name>/SKILL.md`). The SDK does not have a programmatic API for registering skills. See [Agent Skills in the SDK](/en/agent-sdk/skills) for full details.

162</Note>

163 

164For more on creating and using skills, see [Agent Skills in the SDK](/en/agent-sdk/skills).

165 

166## Hooks

167 

168The SDK supports two ways to define hooks, and they run side by side:

169 

170* **Filesystem hooks:** shell commands defined in `settings.json`, loaded when `settingSources` includes the relevant source. These are the same hooks you'd configure for [interactive Claude Code sessions](/en/hooks-guide).

171* **Programmatic hooks:** callback functions passed directly to `query()`. These run in your application process and can return structured decisions. See [Control execution with hooks](/en/agent-sdk/hooks).

172 

173Both types execute during the same hook lifecycle. If you already have hooks in your project's `.claude/settings.json` and you set `settingSources: ["project"]`, those hooks run automatically in the SDK with no extra configuration.

174 

175Hook callbacks receive the tool input and return a decision dict. Returning `{}` (an empty dict) means allow the tool to proceed. Returning `{"decision": "block", "reason": "..."}` prevents execution and the reason is sent to Claude as the tool result. See the [hooks guide](/en/agent-sdk/hooks) for the full callback signature and return types.

176 

177<CodeGroup>

178 ```python Python theme={null}

179 from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, ResultMessage

180 

181 

182 # PreToolUse hook callback. Positional args:

183 # input_data: HookInput dict with tool_name, tool_input, hook_event_name

184 # tool_use_id: str | None, the ID of the tool call being intercepted

185 # context: HookContext, carries session metadata

186 async def audit_bash(input_data, tool_use_id, context):

187 command = input_data.get("tool_input", {}).get("command", "")

188 if "rm -rf" in command:

189 return {"decision": "block", "reason": "Destructive command blocked"}

190 return {} # Empty dict: allow the tool to proceed

191 

192 

193 # Filesystem hooks from .claude/settings.json run automatically

194 # when settingSources loads them. You can also add programmatic hooks:

195 async for message in query(

196 prompt="Refactor the auth module",

197 options=ClaudeAgentOptions(

198 setting_sources=["project"], # Loads hooks from .claude/settings.json

199 hooks={

200 "PreToolUse": [

201 HookMatcher(matcher="Bash", hooks=[audit_bash]),

202 ]

203 },

204 ),

205 ):

206 if isinstance(message, ResultMessage) and message.subtype == "success":

207 print(message.result)

208 ```

209 

210 ```typescript TypeScript theme={null}

211 import { query, type HookInput, type HookJSONOutput } from "@anthropic-ai/claude-agent-sdk";

212 

213 // PreToolUse hook callback. HookInput is a discriminated union on

214 // hook_event_name, so narrowing on it gives TypeScript the right

215 // tool_input shape for this event.

216 const auditBash = async (input: HookInput): Promise<HookJSONOutput> => {

217 if (input.hook_event_name !== "PreToolUse") return {};

218 const toolInput = input.tool_input as { command?: string };

219 if (toolInput.command?.includes("rm -rf")) {

220 return { decision: "block", reason: "Destructive command blocked" };

221 }

222 return {}; // Empty object: allow the tool to proceed

223 };

224 

225 // Filesystem hooks from .claude/settings.json run automatically

226 // when settingSources loads them. You can also add programmatic hooks:

227 for await (const message of query({

228 prompt: "Refactor the auth module",

229 options: {

230 settingSources: ["project"], // Loads hooks from .claude/settings.json

231 hooks: {

232 PreToolUse: [{ matcher: "Bash", hooks: [auditBash] }]

233 }

234 }

235 })) {

236 if (message.type === "result" && message.subtype === "success") {

237 console.log(message.result);

238 }

239 }

240 ```

241</CodeGroup>

242 

243### When to use which hook type

244 

245| Hook type | Best for |

246| :---------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

247| **Filesystem** (`settings.json`) | Sharing hooks between CLI and SDK sessions. Supports `"command"` (shell scripts), `"http"` (POST to an endpoint), `"mcp_tool"` (call a connected MCP server's tool), `"prompt"` (LLM evaluates a prompt), and `"agent"` (spawns a verifier agent). These fire in the main agent and any subagents it spawns. |

248| **Programmatic** (callbacks in `query()`) | Application-specific logic; returning structured decisions; in-process integration. Scoped to the main session only. |

249 

250<Note>

251 The TypeScript SDK supports additional hook events beyond Python, including `SessionStart`, `SessionEnd`, `TeammateIdle`, and `TaskCompleted`. See the [hooks guide](/en/agent-sdk/hooks) for the full event compatibility table.

252</Note>

253 

254For full details on programmatic hooks, see [Control execution with hooks](/en/agent-sdk/hooks). For filesystem hook syntax, see [Hooks](/en/hooks).

255 

256## Choose the right feature

257 

258The Agent SDK gives you access to several ways to extend your agent's behavior. If you're unsure which to use, this table maps common goals to the right approach.

259 

260| You want to... | Use | SDK surface |

261| :------------------------------------------------------------------------------------------------ | :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |

262| Set project conventions your agent always follows | [CLAUDE.md](/en/memory) | `settingSources: ["project"]` loads it automatically |

263| Give the agent reference material it loads when relevant | [Skills](/en/agent-sdk/skills) | `settingSources` + `allowedTools: ["Skill"]` |

264| Run a reusable workflow (deploy, review, release) | [User-invocable skills](/en/agent-sdk/skills) | `settingSources` + `allowedTools: ["Skill"]` |

265| Delegate an isolated subtask to a fresh context (research, review) | [Subagents](/en/agent-sdk/subagents) | `agents` parameter + `allowedTools: ["Agent"]` |

266| Coordinate multiple Claude Code instances with shared task lists and direct inter-agent messaging | [Agent teams](/en/agent-teams) | Not directly configured via SDK options. Agent teams are a CLI feature where one session acts as the team lead, coordinating work across independent teammates |

267| Run deterministic logic on tool calls (audit, block, transform) | [Hooks](/en/agent-sdk/hooks) | `hooks` parameter with callbacks, or shell scripts loaded via `settingSources` |

268| Give Claude structured tool access to an external service | [MCP](/en/agent-sdk/mcp) | `mcpServers` parameter |

269 

270<Tip>

271 **Subagents versus agent teams:** Subagents are ephemeral and isolated: fresh conversation, one task, summary returned to parent. Agent teams coordinate multiple independent Claude Code instances that share a task list and message each other directly. Agent teams are a CLI feature. See [What subagents inherit](/en/agent-sdk/subagents#what-subagents-inherit) and the [agent teams comparison](/en/agent-teams#compare-with-subagents) for details.

272</Tip>

273 

274Every feature you enable adds to your agent's context window. For per-feature costs and how these features layer together, see [Extend Claude Code](/en/features-overview#understand-context-costs).

275 

276## Related resources

277 

278* [Extend Claude Code](/en/features-overview): Conceptual overview of all extension features, with comparison tables and context cost analysis

279* [Skills in the SDK](/en/agent-sdk/skills): Full guide to using skills programmatically

280* [Subagents](/en/agent-sdk/subagents): Define and invoke subagents for isolated subtasks

281* [Hooks](/en/agent-sdk/hooks): Intercept and control agent behavior at key execution points

282* [Permissions](/en/agent-sdk/permissions): Control tool access with modes, rules, and callbacks

283* [System prompts](/en/agent-sdk/modifying-system-prompts): Inject context without CLAUDE.md files

agent-sdk/cost-tracking.md +263 −0 added

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# Track cost and usage

6 

7> Learn how to track token usage, estimate costs, and configure prompt caching with the Claude Agent SDK.

8 

9The Claude Agent SDK provides detailed token usage information for each interaction with Claude. This guide explains how to properly track usage and understand cost reporting, especially when dealing with parallel tool uses and multi-step conversations.

10 

11For complete API documentation, see the [TypeScript SDK reference](/en/agent-sdk/typescript) and [Python SDK reference](/en/agent-sdk/python).

12 

13<Warning>

14 The `total_cost_usd` and `costUSD` fields are client-side estimates, not authoritative billing data. The SDK computes them locally from a price table bundled at build time, so they can drift from what you are actually billed when:

15 

16 * pricing changes

17 * the installed SDK version does not recognize a model

18 * billing rules apply that the client cannot model

19 

20 Use these fields for development insight and approximate budgeting. For authoritative billing, use the [Usage and Cost API](https://platform.claude.com/docs/en/build-with-claude/usage-cost-api) or the Usage page in the [Claude Console](https://platform.claude.com/usage). Do not bill end users or trigger financial decisions from these fields.

21</Warning>

22 

23## Understand token usage

24 

25The TypeScript and Python SDKs expose the same usage data with different field names:

26 

27* **TypeScript** provides per-step token breakdowns on each assistant message (`message.message.id`, `message.message.usage`), per-model cost via `modelUsage` on the result message, and a cumulative total on the result message.

28* **Python** provides per-step token breakdowns on each assistant message (`message.usage`, `message.message_id`), per-model cost via `model_usage` on the result message, and the accumulated total on the result message (`total_cost_usd` and `usage` dict).

29 

30Both SDKs use the same underlying cost model and expose the same granularity. The difference is in field naming and where per-step usage is nested.

31 

32Cost tracking depends on understanding how the SDK scopes usage data:

33 

34* **`query()` call:** one invocation of the SDK's `query()` function. A single call can involve multiple steps (Claude responds, uses tools, gets results, responds again). Each call produces one [`result`](/en/agent-sdk/typescript#sdk-result-message) message at the end.

35* **Step:** a single request/response cycle within a `query()` call. Each step produces assistant messages with token usage.

36* **Session:** a series of `query()` calls linked by a session ID (using the `resume` option). Each `query()` call within a session reports its own cost independently.

37 

38The following diagram shows the message stream from a single `query()` call, with token usage reported at each step and the cumulative estimate at the end:

39 

40<img src="https://mintcdn.com/claude-code/Dujg43sxTkuhSELI/images/agent-sdk/message-usage-flow.svg?fit=max&auto=format&n=Dujg43sxTkuhSELI&q=85&s=c542f51ff58547ef9c0e57b16d03f33c" alt="Diagram showing a query producing two steps of messages. Step 1 has four assistant messages sharing the same ID and usage (count once), Step 2 has one assistant message with a new ID, and the final result message shows the estimated total_cost_usd." width="760" height="520" data-path="images/agent-sdk/message-usage-flow.svg" />

41 

42<Steps>

43 <Step title="Each step produces assistant messages">

44 When Claude responds, it sends one or more assistant messages. In TypeScript, each assistant message contains a nested `BetaMessage` (accessed via `message.message`) with an `id` and a [`usage`](https://platform.claude.com/docs/en/api/messages) object with token counts (`input_tokens`, `output_tokens`). In Python, the `AssistantMessage` dataclass exposes the same data directly via `message.usage` and `message.message_id`. When Claude uses multiple tools in one turn, all messages in that turn share the same ID, so deduplicate by ID to avoid double-counting.

45 </Step>

46 

47 <Step title="The result message provides the cumulative estimate">

48 When the `query()` call completes, the SDK emits a result message with `total_cost_usd` and cumulative `usage`. This is available in both TypeScript ([`SDKResultMessage`](/en/agent-sdk/typescript#sdk-result-message)) and Python ([`ResultMessage`](/en/agent-sdk/python#result-message)). If you make multiple `query()` calls (for example, in a multi-turn session), each result only reflects the cost of that individual call. If you only need the estimated total, you can ignore the per-step usage and read this single value.

49 </Step>

50</Steps>

51 

52## Get the total cost of a query

53 

54The result message ([TypeScript](/en/agent-sdk/typescript#sdk-result-message), [Python](/en/agent-sdk/python#result-message)) marks the end of the agent loop for a `query()` call. It includes `total_cost_usd`, the cumulative estimated cost across all steps in that call. This works for both success and error results. If you use sessions to make multiple `query()` calls, each result only reflects the cost of that individual call.

55 

56The following examples iterate over the message stream from a `query()` call and print the total cost when the `result` message arrives:

57 

58<CodeGroup>

59 ```typescript TypeScript theme={null}

60 import { query } from "@anthropic-ai/claude-agent-sdk";

61 

62 for await (const message of query({ prompt: "Summarize this project" })) {

63 if (message.type === "result") {

64 console.log(`Total cost: $${message.total_cost_usd}`);

65 }

66 }

67 ```

68 

69 ```python Python theme={null}

70 from claude_agent_sdk import query, ResultMessage

71 import asyncio

72 

73 

74 async def main():

75 async for message in query(prompt="Summarize this project"):

76 if isinstance(message, ResultMessage):

77 print(f"Total cost: ${message.total_cost_usd or 0}")

78 

79 

80 asyncio.run(main())

81 ```

82</CodeGroup>

83 

84## Track per-step and per-model usage

85 

86The examples in this section use TypeScript field names. In Python, the equivalent fields are [`AssistantMessage.usage`](/en/agent-sdk/python#assistant-message) and `AssistantMessage.message_id` for per-step usage, and [`ResultMessage.model_usage`](/en/agent-sdk/python#result-message) for per-model breakdowns.

87 

88### Track per-step usage

89 

90Each assistant message contains a nested `BetaMessage` (accessed via `message.message`) with an `id` and `usage` object with token counts. When Claude uses tools in parallel, multiple messages share the same `id` with identical usage data. Track which IDs you've already counted and skip duplicates to avoid inflated totals.

91 

92<Warning>

93 Parallel tool calls produce multiple assistant messages whose nested `BetaMessage` shares the same `id` and identical usage. Always deduplicate by ID to get accurate per-step token counts.

94</Warning>

95 

96The following example accumulates input and output tokens across all steps, counting each unique message ID only once:

97 

98```typescript theme={null}

99import { query } from "@anthropic-ai/claude-agent-sdk";

100 

101const seenIds = new Set<string>();

102let totalInputTokens = 0;

103let totalOutputTokens = 0;

104 

105for await (const message of query({ prompt: "Summarize this project" })) {

106 if (message.type === "assistant") {

107 const msgId = message.message.id;

108 

109 // Parallel tool calls share the same ID, only count once

110 if (!seenIds.has(msgId)) {

111 seenIds.add(msgId);

112 totalInputTokens += message.message.usage.input_tokens;

113 totalOutputTokens += message.message.usage.output_tokens;

114 }

115 }

116}

117 

118console.log(`Steps: ${seenIds.size}`);

119console.log(`Input tokens: ${totalInputTokens}`);

120console.log(`Output tokens: ${totalOutputTokens}`);

121```

122 

123### Break down usage per model

124 

125The result message includes [`modelUsage`](/en/agent-sdk/typescript#model-usage), a map of model name to per-model token counts and cost. This is useful when you run multiple models (for example, Haiku for subagents and Opus for the main agent) and want to see where tokens are going.

126 

127The following example runs a query and prints the cost and token breakdown for each model used:

128 

129```typescript theme={null}

130import { query } from "@anthropic-ai/claude-agent-sdk";

131 

132for await (const message of query({ prompt: "Summarize this project" })) {

133 if (message.type !== "result") continue;

134 

135 for (const [modelName, usage] of Object.entries(message.modelUsage)) {

136 console.log(`${modelName}: $${usage.costUSD.toFixed(4)}`);

137 console.log(` Input tokens: ${usage.inputTokens}`);

138 console.log(` Output tokens: ${usage.outputTokens}`);

139 console.log(` Cache read: ${usage.cacheReadInputTokens}`);

140 console.log(` Cache creation: ${usage.cacheCreationInputTokens}`);

141 }

142}

143```

144 

145## Accumulate costs across multiple calls

146 

147Each `query()` call returns its own `total_cost_usd`. The SDK does not provide a session-level total, so if your application makes multiple `query()` calls (for example, in a multi-turn session or across different users), accumulate the totals yourself.

148 

149The following examples run two `query()` calls sequentially, add each call's `total_cost_usd` to a running total, and print both the per-call and combined cost:

150 

151<CodeGroup>

152 ```typescript TypeScript theme={null}

153 import { query } from "@anthropic-ai/claude-agent-sdk";

154 

155 // Track cumulative cost across multiple query() calls

156 let totalSpend = 0;

157 

158 const prompts = [

159 "Read the files in src/ and summarize the architecture",

160 "List all exported functions in src/auth.ts"

161 ];

162 

163 for (const prompt of prompts) {

164 for await (const message of query({ prompt })) {

165 if (message.type === "result") {

166 totalSpend += message.total_cost_usd;

167 console.log(`This call: $${message.total_cost_usd}`);

168 }

169 }

170 }

171 

172 console.log(`Total spend: $${totalSpend.toFixed(4)}`);

173 ```

174 

175 ```python Python theme={null}

176 from claude_agent_sdk import query, ResultMessage

177 import asyncio

178 

179 

180 async def main():

181 # Track cumulative cost across multiple query() calls

182 total_spend = 0.0

183 

184 prompts = [

185 "Read the files in src/ and summarize the architecture",

186 "List all exported functions in src/auth.ts",

187 ]

188 

189 for prompt in prompts:

190 async for message in query(prompt=prompt):

191 if isinstance(message, ResultMessage):

192 cost = message.total_cost_usd or 0

193 total_spend += cost

194 print(f"This call: ${cost}")

195 

196 print(f"Total spend: ${total_spend:.4f}")

197 

198 

199 asyncio.run(main())

200 ```

201</CodeGroup>

202 

203## Handle errors, caching, and token discrepancies

204 

205For accurate cost tracking, account for failed conversations, cache token pricing, and occasional reporting inconsistencies.

206 

207### Resolve output token discrepancies

208 

209In rare cases, you might observe different `output_tokens` values for messages with the same ID. When this occurs:

210 

2111. **Use the highest value:** the final message in a group typically contains the accurate total.

2122. **Prefer the result message:** the `total_cost_usd` in the result message reflects the SDK's accumulated estimate across all steps, so it is more reliable than summing per-step values yourself. It is still an estimate and may differ from your actual bill.

2133. **Report inconsistencies:** file issues at the [Claude Code GitHub repository](https://github.com/anthropics/claude-code/issues).

214 

215### Track costs on failed conversations

216 

217Both success and error result messages include `usage` and `total_cost_usd`. If a conversation fails mid-way, you still consumed tokens up to the point of failure. Always read cost data from the result message regardless of its `subtype`.

218 

219### Track cache tokens

220 

221The Agent SDK automatically uses [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) to reduce costs on repeated content. You do not need to configure caching yourself. The usage object includes two additional fields for cache tracking:

222 

223* `cache_creation_input_tokens`: tokens used to create new cache entries (charged at a higher rate than standard input tokens).

224* `cache_read_input_tokens`: tokens read from existing cache entries (charged at a reduced rate).

225 

226Track these separately from `input_tokens` to understand caching savings. In TypeScript, these fields are typed on the [`Usage`](/en/agent-sdk/typescript#usage) object. In Python, they appear as keys in the [`ResultMessage.usage`](/en/agent-sdk/python#result-message) dict (for example, `message.usage.get("cache_read_input_tokens", 0)`).

227 

228### Extend the prompt cache TTL to one hour

229 

230Cache entries written by the SDK use a 5-minute TTL by default when you authenticate with an API key or run on Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If your workload runs many short sessions against the same system prompt and context with gaps longer than 5 minutes between them, the cache expires between sessions and each new session pays full input price.

231 

232To request a 1-hour TTL on cache writes, set the [`ENABLE_PROMPT_CACHING_1H`](/en/env-vars) environment variable. You can export it in your shell or container environment, or pass it through `options.env`.

233 

234The following example enables 1-hour TTL for an agent running on Bedrock:

235 

236<CodeGroup>

237 ```python Python theme={null}

238 options = ClaudeAgentOptions(

239 env={

240 "CLAUDE_CODE_USE_BEDROCK": "1",

241 "ENABLE_PROMPT_CACHING_1H": "1",

242 },

243 )

244 ```

245 

246 ```typescript TypeScript theme={null}

247 const options = {

248 env: {

249 ...process.env,

250 CLAUDE_CODE_USE_BEDROCK: "1",

251 ENABLE_PROMPT_CACHING_1H: "1",

252 },

253 };

254 ```

255</CodeGroup>

256 

257Cache writes with a 1-hour TTL are billed at a higher rate than 5-minute writes, so enabling this trades higher write cost for more cache reads. See [prompt caching pricing](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) for details. Claude subscription users already receive 1-hour TTL automatically and do not need to set this variable.

258 

259## Related documentation

260 

261* [TypeScript SDK Reference](/en/agent-sdk/typescript) - Complete API documentation

262* [SDK Overview](/en/agent-sdk/overview) - Getting started with the SDK

263* [SDK Permissions](/en/agent-sdk/permissions) - Managing tool permissions

agent-sdk/custom-tools.md +804 −0 added

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# Give Claude custom tools

6 

7> Define custom tools with the Claude Agent SDK's in-process MCP server so Claude can call your functions, hit your APIs, and perform domain-specific operations.

8 

9Custom tools extend the Agent SDK by letting you define your own functions that Claude can call during a conversation. Using the SDK's in-process MCP server, you can give Claude access to databases, external APIs, domain-specific logic, or any other capability your application needs.

10 

11This guide covers how to define tools with input schemas and handlers, bundle them into an MCP server, pass them to `query`, and control which tools Claude can access. It also covers error handling, tool annotations, and returning non-text content like images.

12 

13## Quick reference

14 

15| If you want to... | Do this |

16| :------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

17| Define a tool | Use [`@tool`](/en/agent-sdk/python#tool) (Python) or [`tool()`](/en/agent-sdk/typescript#tool) (TypeScript) with a name, description, schema, and handler. See [Create a custom tool](#create-a-custom-tool). |

18| Register a tool with Claude | Wrap in `create_sdk_mcp_server` / `createSdkMcpServer` and pass to `mcpServers` in `query()`. See [Call a custom tool](#call-a-custom-tool). |

19| Pre-approve a tool | Add to your allowed tools. See [Configure allowed tools](#configure-allowed-tools). |

20| Remove a built-in tool from Claude's context | Pass a `tools` array listing only the built-ins you want. See [Configure allowed tools](#configure-allowed-tools). |

21| Let Claude call tools in parallel | Set `readOnlyHint: true` on tools with no side effects. See [Add tool annotations](#add-tool-annotations). |

22| Handle errors without stopping the loop | Return `isError: true` instead of throwing. See [Handle errors](#handle-errors). |

23| Return images or files | Use `image` or `resource` blocks in the content array. See [Return images and resources](#return-images-and-resources). |

24| Scale to many tools | Use [tool search](/en/agent-sdk/tool-search) to load tools on demand. |

25 

26## Create a custom tool

27 

28A tool is defined by four parts, passed as arguments to the [`tool()`](/en/agent-sdk/typescript#tool) helper in TypeScript or the [`@tool`](/en/agent-sdk/python#tool) decorator in Python:

29 

30* **Name:** a unique identifier Claude uses to call the tool.

31* **Description:** what the tool does. Claude reads this to decide when to call it.

32* **Input schema:** the arguments Claude must provide. In TypeScript this is always a [Zod schema](https://zod.dev/), and the handler's `args` are typed from it automatically. In Python this is a dict mapping names to types, like `{"latitude": float}`, which the SDK converts to JSON Schema for you. The Python decorator also accepts a full [JSON Schema](https://json-schema.org/understanding-json-schema/about) dict directly when you need enums, ranges, optional fields, or nested objects.

33* **Handler:** the async function that runs when Claude calls the tool. It receives the validated arguments and must return an object with:

34 * `content` (required): an array of result blocks, each with a `type` of `"text"`, `"image"`, or `"resource"`. See [Return images and resources](#return-images-and-resources) for non-text blocks.

35 * `isError` (optional): set to `true` to signal a tool failure so Claude can react to it. See [Handle errors](#handle-errors).

36 

37After defining a tool, wrap it in a server with [`createSdkMcpServer`](/en/agent-sdk/typescript#create-sdk-mcp-server) (TypeScript) or [`create_sdk_mcp_server`](/en/agent-sdk/python#create-sdk-mcp-server) (Python). The server runs in-process inside your application, not as a separate process.

38 

39### Weather tool example

40 

41This example defines a `get_temperature` tool and wraps it in an MCP server. It only sets up the tool; to pass it to `query` and run it, see [Call a custom tool](#call-a-custom-tool) below.

42 

43<CodeGroup>

44 ```python Python theme={null}

45 from typing import Any

46 import httpx

47 from claude_agent_sdk import tool, create_sdk_mcp_server

48 

49 

50 # Define a tool: name, description, input schema, handler

51 @tool(

52 "get_temperature",

53 "Get the current temperature at a location",

54 {"latitude": float, "longitude": float},

55 )

56 async def get_temperature(args: dict[str, Any]) -> dict[str, Any]:

57 async with httpx.AsyncClient() as client:

58 response = await client.get(

59 "https://api.open-meteo.com/v1/forecast",

60 params={

61 "latitude": args["latitude"],

62 "longitude": args["longitude"],

63 "current": "temperature_2m",

64 "temperature_unit": "fahrenheit",

65 },

66 )

67 data = response.json()

68 

69 # Return a content array - Claude sees this as the tool result

70 return {

71 "content": [

72 {

73 "type": "text",

74 "text": f"Temperature: {data['current']['temperature_2m']}°F",

75 }

76 ]

77 }

78 

79 

80 # Wrap the tool in an in-process MCP server

81 weather_server = create_sdk_mcp_server(

82 name="weather",

83 version="1.0.0",

84 tools=[get_temperature],

85 )

86 ```

87 

88 ```typescript TypeScript theme={null}

89 import { tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";

90 import { z } from "zod";

91 

92 // Define a tool: name, description, input schema, handler

93 const getTemperature = tool(

94 "get_temperature",

95 "Get the current temperature at a location",

96 {

97 latitude: z.number().describe("Latitude coordinate"), // .describe() adds a field description Claude sees

98 longitude: z.number().describe("Longitude coordinate")

99 },

100 async (args) => {

101 // args is typed from the schema: { latitude: number; longitude: number }

102 const response = await fetch(

103 `https://api.open-meteo.com/v1/forecast?latitude=${args.latitude}&longitude=${args.longitude}&current=temperature_2m&temperature_unit=fahrenheit`

104 );

105 const data: any = await response.json();

106 

107 // Return a content array - Claude sees this as the tool result

108 return {

109 content: [{ type: "text", text: `Temperature: ${data.current.temperature_2m}°F` }]

110 };

111 }

112 );

113 

114 // Wrap the tool in an in-process MCP server

115 const weatherServer = createSdkMcpServer({

116 name: "weather",

117 version: "1.0.0",

118 tools: [getTemperature]

119 });

120 ```

121</CodeGroup>

122 

123See the [`tool()`](/en/agent-sdk/typescript#tool) TypeScript reference or the [`@tool`](/en/agent-sdk/python#tool) Python reference for full parameter details, including JSON Schema input formats and return value structure.

124 

125<Tip>

126 To make a parameter optional: in TypeScript, add `.default()` to the Zod field. In Python, the dict schema treats every key as required, so leave the parameter out of the schema, mention it in the description string, and read it with `args.get()` in the handler. The [`get_precipitation_chance` tool below](#add-more-tools) shows both patterns.

127</Tip>

128 

129### Call a custom tool

130 

131Pass the MCP server you created to `query` via the `mcpServers` option. The key in `mcpServers` becomes the `{server_name}` segment in each tool's fully qualified name: `mcp__{server_name}__{tool_name}`. List that name in `allowedTools` so the tool runs without a permission prompt.

132 

133These snippets reuse the `weatherServer` from the [example above](#weather-tool-example) to ask Claude what the weather is in a specific location.

134 

135<CodeGroup>

136 ```python Python theme={null}

137 import asyncio

138 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

139 

140 

141 async def main():

142 options = ClaudeAgentOptions(

143 mcp_servers={"weather": weather_server},

144 allowed_tools=["mcp__weather__get_temperature"],

145 )

146 

147 async for message in query(

148 prompt="What's the temperature in San Francisco?",

149 options=options,

150 ):

151 # ResultMessage is the final message after all tool calls complete

152 if isinstance(message, ResultMessage) and message.subtype == "success":

153 print(message.result)

154 

155 

156 asyncio.run(main())

157 ```

158 

159 ```typescript TypeScript theme={null}

160 import { query } from "@anthropic-ai/claude-agent-sdk";

161 

162 for await (const message of query({

163 prompt: "What's the temperature in San Francisco?",

164 options: {

165 mcpServers: { weather: weatherServer },

166 allowedTools: ["mcp__weather__get_temperature"]

167 }

168 })) {

169 // "result" is the final message after all tool calls complete

170 if (message.type === "result" && message.subtype === "success") {

171 console.log(message.result);

172 }

173 }

174 ```

175</CodeGroup>

176 

177### Add more tools

178 

179A server holds as many tools as you list in its `tools` array. With more than one tool on a server, you can list each one in `allowedTools` individually or use the wildcard `mcp__weather__*` to cover every tool the server exposes.

180 

181The example below adds a second tool, `get_precipitation_chance`, to the `weatherServer` from the [weather tool example](#weather-tool-example) and rebuilds it with both tools in the array.

182 

183<CodeGroup>

184 ```python Python theme={null}

185 # Define a second tool for the same server

186 @tool(

187 "get_precipitation_chance",

188 "Get the hourly precipitation probability for a location. "

189 "Optionally pass 'hours' (1-24) to control how many hours to return.",

190 {"latitude": float, "longitude": float},

191 )

192 async def get_precipitation_chance(args: dict[str, Any]) -> dict[str, Any]:

193 # 'hours' isn't in the schema - read it with .get() to make it optional

194 hours = args.get("hours", 12)

195 async with httpx.AsyncClient() as client:

196 response = await client.get(

197 "https://api.open-meteo.com/v1/forecast",

198 params={

199 "latitude": args["latitude"],

200 "longitude": args["longitude"],

201 "hourly": "precipitation_probability",

202 "forecast_days": 1,

203 },

204 )

205 data = response.json()

206 chances = data["hourly"]["precipitation_probability"][:hours]

207 

208 return {

209 "content": [

210 {

211 "type": "text",

212 "text": f"Next {hours} hours: {'%, '.join(map(str, chances))}%",

213 }

214 ]

215 }

216 

217 

218 # Rebuild the server with both tools in the array

219 weather_server = create_sdk_mcp_server(

220 name="weather",

221 version="1.0.0",

222 tools=[get_temperature, get_precipitation_chance],

223 )

224 ```

225 

226 ```typescript TypeScript theme={null}

227 // Define a second tool for the same server

228 const getPrecipitationChance = tool(

229 "get_precipitation_chance",

230 "Get the hourly precipitation probability for a location",

231 {

232 latitude: z.number(),

233 longitude: z.number(),

234 hours: z

235 .number()

236 .int()

237 .min(1)

238 .max(24)

239 .default(12) // .default() makes the parameter optional

240 .describe("How many hours of forecast to return")

241 },

242 async (args) => {

243 const response = await fetch(

244 `https://api.open-meteo.com/v1/forecast?latitude=${args.latitude}&longitude=${args.longitude}&hourly=precipitation_probability&forecast_days=1`

245 );

246 const data: any = await response.json();

247 const chances = data.hourly.precipitation_probability.slice(0, args.hours);

248 

249 return {

250 content: [{ type: "text", text: `Next ${args.hours} hours: ${chances.join("%, ")}%` }]

251 };

252 }

253 );

254 

255 // Rebuild the server with both tools in the array

256 const weatherServer = createSdkMcpServer({

257 name: "weather",

258 version: "1.0.0",

259 tools: [getTemperature, getPrecipitationChance]

260 });

261 ```

262</CodeGroup>

263 

264Every tool in this array consumes context window space on every turn. If you're defining dozens of tools, see [tool search](/en/agent-sdk/tool-search) to load them on demand instead.

265 

266### Add tool annotations

267 

268[Tool annotations](https://modelcontextprotocol.io/docs/concepts/tools#tool-annotations) are optional metadata describing how a tool behaves. Pass them as the fifth argument to `tool()` helper in TypeScript or via the `annotations` keyword argument for the `@tool` decorator in Python. All hint fields are Booleans.

269 

270| Field | Default | Meaning |

271| :---------------- | :------ | :-------------------------------------------------------------------------------------------------------------------- |

272| `readOnlyHint` | `false` | Tool does not modify its environment. Controls whether the tool can be called in parallel with other read-only tools. |

273| `destructiveHint` | `true` | Tool may perform destructive updates. Informational only. |

274| `idempotentHint` | `false` | Repeated calls with the same arguments have no additional effect. Informational only. |

275| `openWorldHint` | `true` | Tool reaches systems outside your process. Informational only. |

276 

277Annotations are metadata, not enforcement. A tool marked `readOnlyHint: true` can still write to disk if that's what the handler does. Keep the annotation accurate to the handler.

278 

279This example adds `readOnlyHint` to the `get_temperature` tool from the [weather tool example](#weather-tool-example).

280 

281<CodeGroup>

282 ```python Python theme={null}

283 from claude_agent_sdk import tool, ToolAnnotations

284 

285 

286 @tool(

287 "get_temperature",

288 "Get the current temperature at a location",

289 {"latitude": float, "longitude": float},

290 annotations=ToolAnnotations(

291 readOnlyHint=True

292 ), # Lets Claude batch this with other read-only calls

293 )

294 async def get_temperature(args):

295 return {"content": [{"type": "text", "text": "..."}]}

296 ```

297 

298 ```typescript TypeScript theme={null}

299 tool(

300 "get_temperature",

301 "Get the current temperature at a location",

302 { latitude: z.number(), longitude: z.number() },

303 async (args) => ({ content: [{ type: "text", text: `...` }] }),

304 { annotations: { readOnlyHint: true } } // Lets Claude batch this with other read-only calls

305 );

306 ```

307</CodeGroup>

308 

309See `ToolAnnotations` in the [TypeScript](/en/agent-sdk/typescript#tool-annotations) or [Python](/en/agent-sdk/python#tool-annotations) reference.

310 

311## Control tool access

312 

313The [weather tool example](#weather-tool-example) registered a server and listed tools in `allowedTools`. This section covers how tool names are constructed and how to scope access when you have multiple tools or want to restrict built-ins.

314 

315### Tool name format

316 

317When MCP tools are exposed to Claude, their names follow a specific format:

318 

319* Pattern: `mcp__{server_name}__{tool_name}`

320* Example: A tool named `get_temperature` in server `weather` becomes `mcp__weather__get_temperature`

321 

322### Configure allowed tools

323 

324The `tools` option and the allowed/disallowed lists operate on separate layers. `tools` controls which built-in tools appear in Claude's context. Allowed and disallowed tool lists control whether calls are approved or denied once Claude attempts them.

325 

326| Option | Layer | Effect |

327| :------------------------ | :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |

328| `tools: ["Read", "Grep"]` | Availability | Only the listed built-ins are in Claude's context. Unlisted built-ins are removed. MCP tools are unaffected. |

329| `tools: []` | Availability | All built-ins are removed. Claude can only use your MCP tools. |

330| allowed tools | Permission | Listed tools run without a permission prompt. Unlisted tools remain available; calls go through the [permission flow](/en/agent-sdk/permissions). |

331| disallowed tools | Permission | Every call to a listed tool is denied. The tool stays in Claude's context, so Claude may still attempt it before the call is rejected. |

332 

333To limit which built-ins Claude can use, prefer `tools` over disallowed tools. Omitting a tool from `tools` removes it from context so Claude never attempts it; listing it in `disallowedTools` (Python: `disallowed_tools`) blocks the call but leaves the tool visible, so Claude may waste a turn trying it. See [Configure permissions](/en/agent-sdk/permissions) for the full evaluation order.

334 

335## Handle errors

336 

337How your handler reports errors determines whether the agent loop continues or stops:

338 

339| What happens | Result |

340| :--------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- |

341| Handler throws an uncaught exception | Agent loop stops. Claude never sees the error, and the `query` call fails. |

342| Handler catches the error and returns `isError: true` (TS) / `"is_error": True` (Python) | Agent loop continues. Claude sees the error as data and can retry, try a different tool, or explain the failure. |

343 

344The example below catches two kinds of failures inside the handler instead of letting them throw. A non-200 HTTP status is caught from the response and returned as an error result. A network error or invalid JSON is caught by the surrounding `try/except` (Python) or `try/catch` (TypeScript) and also returned as an error result. In both cases the handler returns normally and the agent loop continues.

345 

346<CodeGroup>

347 ```python Python theme={null}

348 import json

349 import httpx

350 from typing import Any

351 

352 

353 @tool(

354 "fetch_data",

355 "Fetch data from an API",

356 {"endpoint": str}, # Simple schema

357 )

358 async def fetch_data(args: dict[str, Any]) -> dict[str, Any]:

359 try:

360 async with httpx.AsyncClient() as client:

361 response = await client.get(args["endpoint"])

362 if response.status_code != 200:

363 # Return the failure as a tool result so Claude can react to it.

364 # is_error marks this as a failed call rather than odd-looking data.

365 return {

366 "content": [

367 {

368 "type": "text",

369 "text": f"API error: {response.status_code} {response.reason_phrase}",

370 }

371 ],

372 "is_error": True,

373 }

374 

375 data = response.json()

376 return {"content": [{"type": "text", "text": json.dumps(data, indent=2)}]}

377 except Exception as e:

378 # Catching here keeps the agent loop alive. An uncaught exception

379 # would end the whole query() call.

380 return {

381 "content": [{"type": "text", "text": f"Failed to fetch data: {str(e)}"}],

382 "is_error": True,

383 }

384 ```

385 

386 ```typescript TypeScript theme={null}

387 tool(

388 "fetch_data",

389 "Fetch data from an API",

390 {

391 endpoint: z.string().url().describe("API endpoint URL")

392 },

393 async (args) => {

394 try {

395 const response = await fetch(args.endpoint);

396 

397 if (!response.ok) {

398 // Return the failure as a tool result so Claude can react to it.

399 // isError marks this as a failed call rather than odd-looking data.

400 return {

401 content: [

402 {

403 type: "text",

404 text: `API error: ${response.status} ${response.statusText}`

405 }

406 ],

407 isError: true

408 };

409 }

410 

411 const data = await response.json();

412 return {

413 content: [

414 {

415 type: "text",

416 text: JSON.stringify(data, null, 2)

417 }

418 ]

419 };

420 } catch (error) {

421 // Catching here keeps the agent loop alive. An uncaught throw

422 // would end the whole query() call.

423 return {

424 content: [

425 {

426 type: "text",

427 text: `Failed to fetch data: ${error instanceof Error ? error.message : String(error)}`

428 }

429 ],

430 isError: true

431 };

432 }

433 }

434 );

435 ```

436</CodeGroup>

437 

438## Return images and resources

439 

440The `content` array in a tool result accepts `text`, `image`, and `resource` blocks. You can mix them in the same response.

441 

442### Images

443 

444An image block carries the image bytes inline, encoded as base64. There is no URL field. To return an image that lives at a URL, fetch it in the handler, read the response bytes, and base64-encode them before returning. The result is processed as visual input.

445 

446| Field | Type | Notes |

447| :--------- | :-------- | :------------------------------------------------------------------------- |

448| `type` | `"image"` | |

449| `data` | `string` | Base64-encoded bytes. Raw base64 only, no `data:image/...;base64,` prefix |

450| `mimeType` | `string` | Required. For example `image/png`, `image/jpeg`, `image/webp`, `image/gif` |

451 

452<CodeGroup>

453 ```python Python theme={null}

454 import base64

455 import httpx

456 

457 

458 # Define a tool that fetches an image from a URL and returns it to Claude

459 @tool("fetch_image", "Fetch an image from a URL and return it to Claude", {"url": str})

460 async def fetch_image(args):

461 async with httpx.AsyncClient() as client: # Fetch the image bytes

462 response = await client.get(args["url"])

463 

464 return {

465 "content": [

466 {

467 "type": "image",

468 "data": base64.b64encode(response.content).decode(

469 "ascii"

470 ), # Base64-encode the raw bytes

471 "mimeType": response.headers.get(

472 "content-type", "image/png"

473 ), # Read MIME type from the response

474 }

475 ]

476 }

477 ```

478 

479 ```typescript TypeScript theme={null}

480 tool(

481 "fetch_image",

482 "Fetch an image from a URL and return it to Claude",

483 {

484 url: z.string().url()

485 },

486 async (args) => {

487 const response = await fetch(args.url); // Fetch the image bytes

488 const buffer = Buffer.from(await response.arrayBuffer()); // Read into a Buffer for base64 encoding

489 const mimeType = response.headers.get("content-type") ?? "image/png";

490 

491 return {

492 content: [

493 {

494 type: "image",

495 data: buffer.toString("base64"), // Base64-encode the raw bytes

496 mimeType

497 }

498 ]

499 };

500 }

501 );

502 ```

503</CodeGroup>

504 

505### Resources

506 

507A resource block embeds a piece of content identified by a URI. The URI is a label for Claude to reference; the actual content rides in the block's `text` or `blob` field. Use this when your tool produces something that makes sense to address by name later, such as a generated file or a record from an external system.

508 

509| Field | Type | Notes |

510| :------------------ | :----------- | :---------------------------------------------------------- |

511| `type` | `"resource"` | |

512| `resource.uri` | `string` | Identifier for the content. Any URI scheme |

513| `resource.text` | `string` | The content, if it's text. Provide this or `blob`, not both |

514| `resource.blob` | `string` | The content base64-encoded, if it's binary |

515| `resource.mimeType` | `string` | Optional |

516 

517This example shows a resource block returned from inside a tool handler. The URI `file:///tmp/report.md` is a label that Claude can reference later; the SDK does not read from that path.

518 

519<CodeGroup>

520 ```typescript TypeScript theme={null}

521 return {

522 content: [

523 {

524 type: "resource",

525 resource: {

526 uri: "file:///tmp/report.md", // Label for Claude to reference, not a path the SDK reads

527 mimeType: "text/markdown",

528 text: "# Report\n..." // The actual content, inline

529 }

530 }

531 ]

532 };

533 ```

534 

535 ```python Python theme={null}

536 return {

537 "content": [

538 {

539 "type": "resource",

540 "resource": {

541 "uri": "file:///tmp/report.md", # Label for Claude to reference, not a path the SDK reads

542 "mimeType": "text/markdown",

543 "text": "# Report\n...", # The actual content, inline

544 },

545 }

546 ]

547 }

548 ```

549</CodeGroup>

550 

551These block shapes come from the MCP `CallToolResult` type. See the [MCP specification](https://modelcontextprotocol.io/specification/2025-06-18/server/tools#tool-result) for the full definition.

552 

553## Example: unit converter

554 

555This tool converts values between units of length, temperature, and weight. A user can ask "convert 100 kilometers to miles" or "what is 72°F in Celsius," and Claude picks the right unit type and units from the request.

556 

557It demonstrates two patterns:

558 

559* **Enum schemas:** `unit_type` is constrained to a fixed set of values. In TypeScript, use `z.enum()`. In Python, the dict schema doesn't support enums, so the full JSON Schema dict is required.

560* **Unsupported input handling:** when a conversion pair isn't found, the handler returns `isError: true` so Claude can tell the user what went wrong rather than treating a failure as a normal result.

561 

562<CodeGroup>

563 ```python Python theme={null}

564 from typing import Any

565 from claude_agent_sdk import tool, create_sdk_mcp_server

566 

567 

568 # z.enum() in TypeScript becomes an "enum" constraint in JSON Schema.

569 # The dict schema has no equivalent, so full JSON Schema is required.

570 @tool(

571 "convert_units",

572 "Convert a value from one unit to another",

573 {

574 "type": "object",

575 "properties": {

576 "unit_type": {

577 "type": "string",

578 "enum": ["length", "temperature", "weight"],

579 "description": "Category of unit",

580 },

581 "from_unit": {

582 "type": "string",

583 "description": "Unit to convert from, e.g. kilometers, fahrenheit, pounds",

584 },

585 "to_unit": {"type": "string", "description": "Unit to convert to"},

586 "value": {"type": "number", "description": "Value to convert"},

587 },

588 "required": ["unit_type", "from_unit", "to_unit", "value"],

589 },

590 )

591 async def convert_units(args: dict[str, Any]) -> dict[str, Any]:

592 conversions = {

593 "length": {

594 "kilometers_to_miles": lambda v: v * 0.621371,

595 "miles_to_kilometers": lambda v: v * 1.60934,

596 "meters_to_feet": lambda v: v * 3.28084,

597 "feet_to_meters": lambda v: v * 0.3048,

598 },

599 "temperature": {

600 "celsius_to_fahrenheit": lambda v: (v * 9) / 5 + 32,

601 "fahrenheit_to_celsius": lambda v: (v - 32) * 5 / 9,

602 "celsius_to_kelvin": lambda v: v + 273.15,

603 "kelvin_to_celsius": lambda v: v - 273.15,

604 },

605 "weight": {

606 "kilograms_to_pounds": lambda v: v * 2.20462,

607 "pounds_to_kilograms": lambda v: v * 0.453592,

608 "grams_to_ounces": lambda v: v * 0.035274,

609 "ounces_to_grams": lambda v: v * 28.3495,

610 },

611 }

612 

613 key = f"{args['from_unit']}_to_{args['to_unit']}"

614 fn = conversions.get(args["unit_type"], {}).get(key)

615 

616 if not fn:

617 return {

618 "content": [

619 {

620 "type": "text",

621 "text": f"Unsupported conversion: {args['from_unit']} to {args['to_unit']}",

622 }

623 ],

624 "is_error": True,

625 }

626 

627 result = fn(args["value"])

628 return {

629 "content": [

630 {

631 "type": "text",

632 "text": f"{args['value']} {args['from_unit']} = {result:.4f} {args['to_unit']}",

633 }

634 ]

635 }

636 

637 

638 converter_server = create_sdk_mcp_server(

639 name="converter",

640 version="1.0.0",

641 tools=[convert_units],

642 )

643 ```

644 

645 ```typescript TypeScript theme={null}

646 import { tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";

647 import { z } from "zod";

648 

649 const convert = tool(

650 "convert_units",

651 "Convert a value from one unit to another",

652 {

653 unit_type: z.enum(["length", "temperature", "weight"]).describe("Category of unit"),

654 from_unit: z

655 .string()

656 .describe("Unit to convert from, e.g. kilometers, fahrenheit, pounds"),

657 to_unit: z.string().describe("Unit to convert to"),

658 value: z.number().describe("Value to convert")

659 },

660 async (args) => {

661 type Conversions = Record<string, Record<string, (v: number) => number>>;

662 

663 const conversions: Conversions = {

664 length: {

665 kilometers_to_miles: (v) => v * 0.621371,

666 miles_to_kilometers: (v) => v * 1.60934,

667 meters_to_feet: (v) => v * 3.28084,

668 feet_to_meters: (v) => v * 0.3048

669 },

670 temperature: {

671 celsius_to_fahrenheit: (v) => (v * 9) / 5 + 32,

672 fahrenheit_to_celsius: (v) => ((v - 32) * 5) / 9,

673 celsius_to_kelvin: (v) => v + 273.15,

674 kelvin_to_celsius: (v) => v - 273.15

675 },

676 weight: {

677 kilograms_to_pounds: (v) => v * 2.20462,

678 pounds_to_kilograms: (v) => v * 0.453592,

679 grams_to_ounces: (v) => v * 0.035274,

680 ounces_to_grams: (v) => v * 28.3495

681 }

682 };

683 

684 const key = `${args.from_unit}_to_${args.to_unit}`;

685 const fn = conversions[args.unit_type]?.[key];

686 

687 if (!fn) {

688 return {

689 content: [

690 {

691 type: "text",

692 text: `Unsupported conversion: ${args.from_unit} to ${args.to_unit}`

693 }

694 ],

695 isError: true

696 };

697 }

698 

699 const result = fn(args.value);

700 return {

701 content: [

702 {

703 type: "text",

704 text: `${args.value} ${args.from_unit} = ${result.toFixed(4)} ${args.to_unit}`

705 }

706 ]

707 };

708 }

709 );

710 

711 const converterServer = createSdkMcpServer({

712 name: "converter",

713 version: "1.0.0",

714 tools: [convert]

715 });

716 ```

717</CodeGroup>

718 

719Once the server is defined, pass it to `query` the same way as the weather example. This example sends three different prompts in a loop to show the same tool handling different unit types. For each response, it inspects `AssistantMessage` objects (which contain the tool calls Claude made during that turn) and prints each `ToolUseBlock` before printing the final `ResultMessage` text. This lets you see when Claude is using the tool versus answering from its own knowledge.

720 

721<CodeGroup>

722 ```python Python theme={null}

723 import asyncio

724 from claude_agent_sdk import (

725 query,

726 ClaudeAgentOptions,

727 ResultMessage,

728 AssistantMessage,

729 ToolUseBlock,

730 )

731 

732 

733 async def main():

734 options = ClaudeAgentOptions(

735 mcp_servers={"converter": converter_server},

736 allowed_tools=["mcp__converter__convert_units"],

737 )

738 

739 prompts = [

740 "Convert 100 kilometers to miles.",

741 "What is 72°F in Celsius?",

742 "How many pounds is 5 kilograms?",

743 ]

744 

745 for prompt in prompts:

746 async for message in query(prompt=prompt, options=options):

747 if isinstance(message, AssistantMessage):

748 for block in message.content:

749 if isinstance(block, ToolUseBlock):

750 print(f"[tool call] {block.name}({block.input})")

751 elif isinstance(message, ResultMessage) and message.subtype == "success":

752 print(f"Q: {prompt}\nA: {message.result}\n")

753 

754 

755 asyncio.run(main())

756 ```

757 

758 ```typescript TypeScript theme={null}

759 import { query } from "@anthropic-ai/claude-agent-sdk";

760 

761 const prompts = [

762 "Convert 100 kilometers to miles.",

763 "What is 72°F in Celsius?",

764 "How many pounds is 5 kilograms?"

765 ];

766 

767 for (const prompt of prompts) {

768 for await (const message of query({

769 prompt,

770 options: {

771 mcpServers: { converter: converterServer },

772 allowedTools: ["mcp__converter__convert_units"]

773 }

774 })) {

775 if (message.type === "assistant") {

776 for (const block of message.message.content) {

777 if (block.type === "tool_use") {

778 console.log(`[tool call] ${block.name}`, block.input);

779 }

780 }

781 } else if (message.type === "result" && message.subtype === "success") {

782 console.log(`Q: ${prompt}\nA: ${message.result}\n`);

783 }

784 }

785 }

786 ```

787</CodeGroup>

788 

789## Next steps

790 

791Custom tools wrap async functions in a standard interface. You can mix the patterns on this page in the same server: a single server can hold a database tool, an API gateway tool, and an image renderer alongside each other.

792 

793From here:

794 

795* If your server grows to dozens of tools, see [tool search](/en/agent-sdk/tool-search) to defer loading them until Claude needs them.

796* To connect to external MCP servers (filesystem, GitHub, Slack) instead of building your own, see [Connect MCP servers](/en/agent-sdk/mcp).

797* To control which tools run automatically versus requiring approval, see [Configure permissions](/en/agent-sdk/permissions).

798 

799## Related documentation

800 

801* [TypeScript SDK Reference](/en/agent-sdk/typescript)

802* [Python SDK Reference](/en/agent-sdk/python)

803* [MCP Documentation](https://modelcontextprotocol.io)

804* [SDK Overview](/en/agent-sdk/overview)

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# Rewind file changes with checkpointing

6 

7> Track file changes during agent sessions and restore files to any previous state

8 

9File checkpointing tracks file modifications made through the Write, Edit, and NotebookEdit tools during an agent session, allowing you to rewind files to any previous state. Want to try it out? Jump to the [interactive example](#try-it-out).

10 

11With checkpointing, you can:

12 

13* **Undo unwanted changes** by restoring files to a known good state

14* **Explore alternatives** by restoring to a checkpoint and trying a different approach

15* **Recover from errors** when the agent makes incorrect modifications

16 

17<Warning>

18 Only changes made through the Write, Edit, and NotebookEdit tools are tracked. Changes made through Bash commands (like `echo > file.txt` or `sed -i`) are not captured by the checkpoint system.

19</Warning>

20 

21## How checkpointing works

22 

23When you enable file checkpointing, the SDK creates backups of files before modifying them through the Write, Edit, or NotebookEdit tools. User messages in the response stream include a checkpoint UUID that you can use as a restore point.

24 

25Checkpoint works with these built-in tools that the agent uses to modify files:

26 

27| Tool | Description |

28| ------------ | ------------------------------------------------------------------ |

29| Write | Creates a new file or overwrites an existing file with new content |

30| Edit | Makes targeted edits to specific parts of an existing file |

31| NotebookEdit | Modifies cells in Jupyter notebooks (`.ipynb` files) |

32 

33<Note>

34 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).

35</Note>

36 

37The checkpoint system tracks:

38 

39* Files created during the session

40* Files modified during the session

41* The original content of modified files

42 

43When you rewind to a checkpoint, created files are deleted and modified files are restored to their content at that point.

44 

45## Implement checkpointing

46 

47To use file checkpointing, enable it in your options, capture checkpoint UUIDs from the response stream, then call `rewindFiles()` (TypeScript) or `rewind_files()` (Python) when you need to restore.

48 

49The following example shows the complete flow: enable checkpointing, capture the checkpoint UUID and session ID from the response stream, then resume the session later to rewind files. Each step is explained in detail below.

50 

51<CodeGroup>

52 ```python Python theme={null}

53 import asyncio

54 from claude_agent_sdk import (

55 ClaudeSDKClient,

56 ClaudeAgentOptions,

57 UserMessage,

58 ResultMessage,

59 )

60 

61 

62 async def main():

63 # Step 1: Enable checkpointing

64 options = ClaudeAgentOptions(

65 enable_file_checkpointing=True,

66 permission_mode="acceptEdits", # Auto-accept file edits without prompting

67 extra_args={

68 "replay-user-messages": None

69 }, # Required to receive checkpoint UUIDs in the response stream

70 )

71 

72 checkpoint_id = None

73 session_id = None

74 

75 # Run the query and capture checkpoint UUID and session ID

76 async with ClaudeSDKClient(options) as client:

77 await client.query("Refactor the authentication module")

78 

79 # Step 2: Capture checkpoint UUID from the first user message

80 async for message in client.receive_response():

81 if isinstance(message, UserMessage) and message.uuid and not checkpoint_id:

82 checkpoint_id = message.uuid

83 if isinstance(message, ResultMessage) and not session_id:

84 session_id = message.session_id

85 

86 # Step 3: Later, rewind by resuming the session with an empty prompt

87 if checkpoint_id and session_id:

88 async with ClaudeSDKClient(

89 ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)

90 ) as client:

91 await client.query("") # Empty prompt to open the connection

92 async for message in client.receive_response():

93 await client.rewind_files(checkpoint_id)

94 break

95 print(f"Rewound to checkpoint: {checkpoint_id}")

96 

97 

98 asyncio.run(main())

99 ```

100 

101 ```typescript TypeScript theme={null}

102 import { query } from "@anthropic-ai/claude-agent-sdk";

103 

104 async function main() {

105 // Step 1: Enable checkpointing

106 const opts = {

107 enableFileCheckpointing: true,

108 permissionMode: "acceptEdits" as const, // Auto-accept file edits without prompting

109 extraArgs: { "replay-user-messages": null } // Required to receive checkpoint UUIDs in the response stream

110 };

111 

112 const response = query({

113 prompt: "Refactor the authentication module",

114 options: opts

115 });

116 

117 let checkpointId: string | undefined;

118 let sessionId: string | undefined;

119 

120 // Step 2: Capture checkpoint UUID from the first user message

121 for await (const message of response) {

122 if (message.type === "user" && message.uuid && !checkpointId) {

123 checkpointId = message.uuid;

124 }

125 if ("session_id" in message && !sessionId) {

126 sessionId = message.session_id;

127 }

128 }

129 

130 // Step 3: Later, rewind by resuming the session with an empty prompt

131 if (checkpointId && sessionId) {

132 const rewindQuery = query({

133 prompt: "", // Empty prompt to open the connection

134 options: { ...opts, resume: sessionId }

135 });

136 

137 for await (const msg of rewindQuery) {

138 await rewindQuery.rewindFiles(checkpointId);

139 break;

140 }

141 console.log(`Rewound to checkpoint: ${checkpointId}`);

142 }

143 }

144 

145 main();

146 ```

147</CodeGroup>

148 

149<Steps>

150 <Step title="Enable checkpointing">

151 Configure your SDK options to enable checkpointing and receive checkpoint UUIDs:

152 

153 | Option | Python | TypeScript | Description |

154 | ------------------------ | ------------------------------------------- | --------------------------------------------- | ------------------------------------------------ |

155 | Enable checkpointing | `enable_file_checkpointing=True` | `enableFileCheckpointing: true` | Tracks file changes for rewinding |

156 | Receive checkpoint UUIDs | `extra_args={"replay-user-messages": None}` | `extraArgs: { 'replay-user-messages': null }` | Required to get user message UUIDs in the stream |

157 

158 <CodeGroup>

159 ```python Python theme={null}

160 options = ClaudeAgentOptions(

161 enable_file_checkpointing=True,

162 permission_mode="acceptEdits",

163 extra_args={"replay-user-messages": None},

164 )

165 

166 async with ClaudeSDKClient(options) as client:

167 await client.query("Refactor the authentication module")

168 ```

169 

170 ```typescript TypeScript theme={null}

171 const response = query({

172 prompt: "Refactor the authentication module",

173 options: {

174 enableFileCheckpointing: true,

175 permissionMode: "acceptEdits" as const,

176 extraArgs: { "replay-user-messages": null }

177 }

178 });

179 ```

180 </CodeGroup>

181 </Step>

182 

183 <Step title="Capture checkpoint UUID and session ID">

184 With the `replay-user-messages` option set (shown above), each user message in the response stream has a UUID that serves as a checkpoint.

185 

186 For most use cases, capture the first user message UUID (`message.uuid`); rewinding to it restores all files to their original state. To store multiple checkpoints and rewind to intermediate states, see [Multiple restore points](#multiple-restore-points).

187 

188 Capturing the session ID (`message.session_id`) is optional; you only need it if you want to rewind later, after the stream completes. If you're calling `rewindFiles()` immediately while still processing messages (as the example in [Checkpoint before risky operations](#checkpoint-before-risky-operations) does), you can skip capturing the session ID.

189 

190 <CodeGroup>

191 ```python Python theme={null}

192 checkpoint_id = None

193 session_id = None

194 

195 async for message in client.receive_response():

196 # Update checkpoint on each user message (keeps the latest)

197 if isinstance(message, UserMessage) and message.uuid:

198 checkpoint_id = message.uuid

199 # Capture session ID from the result message

200 if isinstance(message, ResultMessage):

201 session_id = message.session_id

202 ```

203 

204 ```typescript TypeScript theme={null}

205 let checkpointId: string | undefined;

206 let sessionId: string | undefined;

207 

208 for await (const message of response) {

209 // Update checkpoint on each user message (keeps the latest)

210 if (message.type === "user" && message.uuid) {

211 checkpointId = message.uuid;

212 }

213 // Capture session ID from any message that has it

214 if ("session_id" in message) {

215 sessionId = message.session_id;

216 }

217 }

218 ```

219 </CodeGroup>

220 </Step>

221 

222 <Step title="Rewind files">

223 To rewind after the stream completes, resume the session with an empty prompt and call `rewind_files()` (Python) or `rewindFiles()` (TypeScript) with your checkpoint UUID. You can also rewind during the stream; see [Checkpoint before risky operations](#checkpoint-before-risky-operations) for that pattern.

224 

225 <CodeGroup>

226 ```python Python theme={null}

227 async with ClaudeSDKClient(

228 ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)

229 ) as client:

230 await client.query("") # Empty prompt to open the connection

231 async for message in client.receive_response():

232 await client.rewind_files(checkpoint_id)

233 break

234 ```

235 

236 ```typescript TypeScript theme={null}

237 const rewindQuery = query({

238 prompt: "", // Empty prompt to open the connection

239 options: { ...opts, resume: sessionId }

240 });

241 

242 for await (const msg of rewindQuery) {

243 await rewindQuery.rewindFiles(checkpointId);

244 break;

245 }

246 ```

247 </CodeGroup>

248 

249 If you capture the session ID and checkpoint ID, you can also rewind from the CLI:

250 

251 ```bash theme={null}

252 claude -p --resume <session-id> --rewind-files <checkpoint-uuid>

253 ```

254 </Step>

255</Steps>

256 

257## Common patterns

258 

259These patterns show different ways to capture and use checkpoint UUIDs depending on your use case.

260 

261### Checkpoint before risky operations

262 

263This pattern keeps only the most recent checkpoint UUID, updating it before each agent turn. If something goes wrong during processing, you can immediately rewind to the last safe state and break out of the loop.

264 

265<CodeGroup>

266 ```python Python theme={null}

267 import asyncio

268 from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, UserMessage

269 

270 

271 async def main():

272 options = ClaudeAgentOptions(

273 enable_file_checkpointing=True,

274 permission_mode="acceptEdits",

275 extra_args={"replay-user-messages": None},

276 )

277 

278 safe_checkpoint = None

279 

280 async with ClaudeSDKClient(options) as client:

281 await client.query("Refactor the authentication module")

282 

283 async for message in client.receive_response():

284 # Update checkpoint before each agent turn starts

285 # This overwrites the previous checkpoint. Only keep the latest

286 if isinstance(message, UserMessage) and message.uuid:

287 safe_checkpoint = message.uuid

288 

289 # Decide when to revert based on your own logic

290 # For example: error detection, validation failure, or user input

291 if your_revert_condition and safe_checkpoint:

292 await client.rewind_files(safe_checkpoint)

293 # Exit the loop after rewinding, files are restored

294 break

295 

296 

297 asyncio.run(main())

298 ```

299 

300 ```typescript TypeScript theme={null}

301 import { query } from "@anthropic-ai/claude-agent-sdk";

302 

303 async function main() {

304 const response = query({

305 prompt: "Refactor the authentication module",

306 options: {

307 enableFileCheckpointing: true,

308 permissionMode: "acceptEdits" as const,

309 extraArgs: { "replay-user-messages": null }

310 }

311 });

312 

313 let safeCheckpoint: string | undefined;

314 

315 for await (const message of response) {

316 // Update checkpoint before each agent turn starts

317 // This overwrites the previous checkpoint. Only keep the latest

318 if (message.type === "user" && message.uuid) {

319 safeCheckpoint = message.uuid;

320 }

321 

322 // Decide when to revert based on your own logic

323 // For example: error detection, validation failure, or user input

324 if (yourRevertCondition && safeCheckpoint) {

325 await response.rewindFiles(safeCheckpoint);

326 // Exit the loop after rewinding, files are restored

327 break;

328 }

329 }

330 }

331 

332 main();

333 ```

334</CodeGroup>

335 

336### Multiple restore points

337 

338If Claude makes changes across multiple turns, you might want to rewind to a specific point rather than all the way back. For example, if Claude refactors a file in turn one and adds tests in turn two, you might want to keep the refactor but undo the tests.

339 

340This pattern stores all checkpoint UUIDs in an array with metadata. After the session completes, you can rewind to any previous checkpoint:

341 

342<CodeGroup>

343 ```python Python theme={null}

344 import asyncio

345 from dataclasses import dataclass

346 from datetime import datetime

347 from claude_agent_sdk import (

348 ClaudeSDKClient,

349 ClaudeAgentOptions,

350 UserMessage,

351 ResultMessage,

352 )

353 

354 

355 # Store checkpoint metadata for better tracking

356 @dataclass

357 class Checkpoint:

358 id: str

359 description: str

360 timestamp: datetime

361 

362 

363 async def main():

364 options = ClaudeAgentOptions(

365 enable_file_checkpointing=True,

366 permission_mode="acceptEdits",

367 extra_args={"replay-user-messages": None},

368 )

369 

370 checkpoints = []

371 session_id = None

372 

373 async with ClaudeSDKClient(options) as client:

374 await client.query("Refactor the authentication module")

375 

376 async for message in client.receive_response():

377 if isinstance(message, UserMessage) and message.uuid:

378 checkpoints.append(

379 Checkpoint(

380 id=message.uuid,

381 description=f"After turn {len(checkpoints) + 1}",

382 timestamp=datetime.now(),

383 )

384 )

385 if isinstance(message, ResultMessage) and not session_id:

386 session_id = message.session_id

387 

388 # Later: rewind to any checkpoint by resuming the session

389 if checkpoints and session_id:

390 target = checkpoints[0] # Pick any checkpoint

391 async with ClaudeSDKClient(

392 ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)

393 ) as client:

394 await client.query("") # Empty prompt to open the connection

395 async for message in client.receive_response():

396 await client.rewind_files(target.id)

397 break

398 print(f"Rewound to: {target.description}")

399 

400 

401 asyncio.run(main())

402 ```

403 

404 ```typescript TypeScript theme={null}

405 import { query } from "@anthropic-ai/claude-agent-sdk";

406 

407 // Store checkpoint metadata for better tracking

408 interface Checkpoint {

409 id: string;

410 description: string;

411 timestamp: Date;

412 }

413 

414 async function main() {

415 const opts = {

416 enableFileCheckpointing: true,

417 permissionMode: "acceptEdits" as const,

418 extraArgs: { "replay-user-messages": null }

419 };

420 

421 const response = query({

422 prompt: "Refactor the authentication module",

423 options: opts

424 });

425 

426 const checkpoints: Checkpoint[] = [];

427 let sessionId: string | undefined;

428 

429 for await (const message of response) {

430 if (message.type === "user" && message.uuid) {

431 checkpoints.push({

432 id: message.uuid,

433 description: `After turn ${checkpoints.length + 1}`,

434 timestamp: new Date()

435 });

436 }

437 if ("session_id" in message && !sessionId) {

438 sessionId = message.session_id;

439 }

440 }

441 

442 // Later: rewind to any checkpoint by resuming the session

443 if (checkpoints.length > 0 && sessionId) {

444 const target = checkpoints[0]; // Pick any checkpoint

445 const rewindQuery = query({

446 prompt: "", // Empty prompt to open the connection

447 options: { ...opts, resume: sessionId }

448 });

449 

450 for await (const msg of rewindQuery) {

451 await rewindQuery.rewindFiles(target.id);

452 break;

453 }

454 console.log(`Rewound to: ${target.description}`);

455 }

456 }

457 

458 main();

459 ```

460</CodeGroup>

461 

462## Try it out

463 

464This complete example creates a small utility file, has the agent add documentation comments, shows you the changes, then asks if you want to rewind.

465 

466Before you begin, make sure you have the [Claude Agent SDK installed](/en/agent-sdk/quickstart).

467 

468<Steps>

469 <Step title="Create a test file">

470 Create a new file called `utils.py` (Python) or `utils.ts` (TypeScript) and paste the following code:

471 

472 <CodeGroup>

473 ```python utils.py theme={null}

474 def add(a, b):

475 return a + b

476 

477 

478 def subtract(a, b):

479 return a - b

480 

481 

482 def multiply(a, b):

483 return a * b

484 

485 

486 def divide(a, b):

487 if b == 0:

488 raise ValueError("Cannot divide by zero")

489 return a / b

490 ```

491 

492 ```typescript utils.ts theme={null}

493 export function add(a: number, b: number): number {

494 return a + b;

495 }

496 

497 export function subtract(a: number, b: number): number {

498 return a - b;

499 }

500 

501 export function multiply(a: number, b: number): number {

502 return a * b;

503 }

504 

505 export function divide(a: number, b: number): number {

506 if (b === 0) {

507 throw new Error("Cannot divide by zero");

508 }

509 return a / b;

510 }

511 ```

512 </CodeGroup>

513 </Step>

514 

515 <Step title="Run the interactive example">

516 Create a new file called `try_checkpointing.py` (Python) or `try_checkpointing.ts` (TypeScript) in the same directory as your utility file, and paste the following code.

517 

518 This script asks Claude to add doc comments to your utility file, then gives you the option to rewind and restore the original.

519 

520 <CodeGroup>

521 ```python try_checkpointing.py theme={null}

522 import asyncio

523 from claude_agent_sdk import (

524 ClaudeSDKClient,

525 ClaudeAgentOptions,

526 UserMessage,

527 ResultMessage,

528 )

529 

530 

531 async def main():

532 # Configure the SDK with checkpointing enabled

533 # - enable_file_checkpointing: Track file changes for rewinding

534 # - permission_mode: Auto-accept file edits without prompting

535 # - extra_args: Required to receive user message UUIDs in the stream

536 options = ClaudeAgentOptions(

537 enable_file_checkpointing=True,

538 permission_mode="acceptEdits",

539 extra_args={"replay-user-messages": None},

540 )

541 

542 checkpoint_id = None # Store the user message UUID for rewinding

543 session_id = None # Store the session ID for resuming

544 

545 print("Running agent to add doc comments to utils.py...\n")

546 

547 # Run the agent and capture checkpoint data from the response stream

548 async with ClaudeSDKClient(options) as client:

549 await client.query("Add doc comments to utils.py")

550 

551 async for message in client.receive_response():

552 # Capture the first user message UUID - this is our restore point

553 if isinstance(message, UserMessage) and message.uuid and not checkpoint_id:

554 checkpoint_id = message.uuid

555 # Capture the session ID so we can resume later

556 if isinstance(message, ResultMessage):

557 session_id = message.session_id

558 

559 print("Done! Open utils.py to see the added doc comments.\n")

560 

561 # Ask the user if they want to rewind the changes

562 if checkpoint_id and session_id:

563 response = input("Rewind to remove the doc comments? (y/n): ")

564 

565 if response.lower() == "y":

566 # Resume the session with an empty prompt, then rewind

567 async with ClaudeSDKClient(

568 ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)

569 ) as client:

570 await client.query("") # Empty prompt opens the connection

571 async for message in client.receive_response():

572 await client.rewind_files(checkpoint_id) # Restore files

573 break

574 

575 print(

576 "\n✓ File restored! Open utils.py to verify the doc comments are gone."

577 )

578 else:

579 print("\nKept the modified file.")

580 

581 

582 asyncio.run(main())

583 ```

584 

585 ```typescript try_checkpointing.ts theme={null}

586 import { query } from "@anthropic-ai/claude-agent-sdk";

587 import * as readline from "readline";

588 

589 async function main() {

590 // Configure the SDK with checkpointing enabled

591 // - enableFileCheckpointing: Track file changes for rewinding

592 // - permissionMode: Auto-accept file edits without prompting

593 // - extraArgs: Required to receive user message UUIDs in the stream

594 const opts = {

595 enableFileCheckpointing: true,

596 permissionMode: "acceptEdits" as const,

597 extraArgs: { "replay-user-messages": null }

598 };

599 

600 let sessionId: string | undefined; // Store the session ID for resuming

601 let checkpointId: string | undefined; // Store the user message UUID for rewinding

602 

603 console.log("Running agent to add doc comments to utils.ts...\n");

604 

605 // Run the agent and capture checkpoint data from the response stream

606 const response = query({

607 prompt: "Add doc comments to utils.ts",

608 options: opts

609 });

610 

611 for await (const message of response) {

612 // Capture the first user message UUID - this is our restore point

613 if (message.type === "user" && message.uuid && !checkpointId) {

614 checkpointId = message.uuid;

615 }

616 // Capture the session ID so we can resume later

617 if ("session_id" in message) {

618 sessionId = message.session_id;

619 }

620 }

621 

622 console.log("Done! Open utils.ts to see the added doc comments.\n");

623 

624 // Ask the user if they want to rewind the changes

625 if (checkpointId && sessionId) {

626 const rl = readline.createInterface({

627 input: process.stdin,

628 output: process.stdout

629 });

630 

631 const answer = await new Promise<string>((resolve) => {

632 rl.question("Rewind to remove the doc comments? (y/n): ", resolve);

633 });

634 rl.close();

635 

636 if (answer.toLowerCase() === "y") {

637 // Resume the session with an empty prompt, then rewind

638 const rewindQuery = query({

639 prompt: "", // Empty prompt opens the connection

640 options: { ...opts, resume: sessionId }

641 });

642 

643 for await (const msg of rewindQuery) {

644 await rewindQuery.rewindFiles(checkpointId); // Restore files

645 break;

646 }

647 

648 console.log("\n✓ File restored! Open utils.ts to verify the doc comments are gone.");

649 } else {

650 console.log("\nKept the modified file.");

651 }

652 }

653 }

654 

655 main();

656 ```

657 </CodeGroup>

658 

659 This example demonstrates the complete checkpointing workflow:

660 

661 1. **Enable checkpointing**: configure the SDK with `enable_file_checkpointing=True` and `permission_mode="acceptEdits"` to auto-approve file edits

662 2. **Capture checkpoint data**: as the agent runs, store the first user message UUID (your restore point) and the session ID

663 3. **Prompt for rewind**: after the agent finishes, check your utility file to see the doc comments, then decide if you want to undo the changes

664 4. **Resume and rewind**: if yes, resume the session with an empty prompt and call `rewind_files()` to restore the original file

665 </Step>

666 

667 <Step title="Run the example">

668 Run the script from the same directory as your utility file.

669 

670 <Tip>

671 Open your utility file (`utils.py` or `utils.ts`) in your IDE or editor before running the script. You'll see the file update in real-time as the agent adds doc comments, then revert back to the original when you choose to rewind.

672 </Tip>

673 

674 <Tabs>

675 <Tab title="Python">

676 ```bash theme={null}

677 python try_checkpointing.py

678 ```

679 </Tab>

680 

681 <Tab title="TypeScript">

682 ```bash theme={null}

683 npx tsx try_checkpointing.ts

684 ```

685 </Tab>

686 </Tabs>

687 

688 You'll see the agent add doc comments, then a prompt asking if you want to rewind. If you choose yes, the file is restored to its original state.

689 </Step>

690</Steps>

691 

692## Limitations

693 

694File checkpointing has the following limitations:

695 

696| Limitation | Description |

697| ---------------------------------- | -------------------------------------------------------------------- |

698| Write/Edit/NotebookEdit tools only | Changes made through Bash commands are not tracked |

699| Same session | Checkpoints are tied to the session that created them |

700| File content only | Creating, moving, or deleting directories is not undone by rewinding |

701| Local files | Remote or network files are not tracked |

702 

703## Troubleshooting

704 

705### Checkpointing options not recognized

706 

707If `enableFileCheckpointing` or `rewindFiles()` isn't available, you may be on an older SDK version.

708 

709**Solution**: Update to the latest SDK version:

710 

711* **Python**: `pip install --upgrade claude-agent-sdk`

712* **TypeScript**: `npm install @anthropic-ai/claude-agent-sdk@latest`

713 

714### User messages don't have UUIDs

715 

716If `message.uuid` is `undefined` or missing, you're not receiving checkpoint UUIDs.

717 

718**Cause**: The `replay-user-messages` option isn't set.

719 

720**Solution**: Add `extra_args={"replay-user-messages": None}` (Python) or `extraArgs: { 'replay-user-messages': null }` (TypeScript) to your options.

721 

722### "No file checkpoint found for message" error

723 

724This error occurs when the checkpoint data doesn't exist for the specified user message UUID.

725 

726**Common causes**:

727 

728* File checkpointing was not enabled on the original session (`enable_file_checkpointing` or `enableFileCheckpointing` was not set to `true`)

729* The session wasn't properly completed before attempting to resume and rewind

730 

731**Solution**: Ensure `enable_file_checkpointing=True` (Python) or `enableFileCheckpointing: true` (TypeScript) was set on the original session, then use the pattern shown in the examples: capture the first user message UUID, complete the session fully, then resume with an empty prompt and call `rewindFiles()` once.

732 

733### "ProcessTransport is not ready for writing" error

734 

735This error occurs when you call `rewindFiles()` or `rewind_files()` after you've finished iterating through the response. The connection to the CLI process closes when the loop completes.

736 

737**Solution**: Resume the session with an empty prompt, then call rewind on the new query:

738 

739<CodeGroup>

740 ```python Python theme={null}

741 # Resume session with empty prompt, then rewind

742 async with ClaudeSDKClient(

743 ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)

744 ) as client:

745 await client.query("")

746 async for message in client.receive_response():

747 await client.rewind_files(checkpoint_id)

748 break

749 ```

750 

751 ```typescript TypeScript theme={null}

752 // Resume session with empty prompt, then rewind

753 const rewindQuery = query({

754 prompt: "",

755 options: { ...opts, resume: sessionId }

756 });

757 

758 for await (const msg of rewindQuery) {

759 await rewindQuery.rewindFiles(checkpointId);

760 break;

761 }

762 ```

763</CodeGroup>

764 

765## Next steps

766 

767* **[Sessions](/en/agent-sdk/sessions)**: learn how to resume sessions, which is required for rewinding after the stream completes. Covers session IDs, resuming conversations, and session forking.

768* **[Permissions](/en/agent-sdk/permissions)**: configure which tools Claude can use and how file modifications are approved. Useful if you want more control over when edits happen.

769* **[TypeScript SDK reference](/en/agent-sdk/typescript)**: complete API reference including all options for `query()` and the `rewindFiles()` method.

770* **[Python SDK reference](/en/agent-sdk/python)**: complete API reference including all options for `ClaudeAgentOptions` and the `rewind_files()` method.

agent-sdk/hooks.md +819 −0 added

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# Intercept and control agent behavior with hooks

6 

7> Intercept and customize agent behavior at key execution points with hooks

8 

9Hooks are callback functions that run your code in response to agent events, like a tool being called, a session starting, or execution stopping. With hooks, you can:

10 

11* **Block dangerous operations** before they execute, like destructive shell commands or unauthorized file access

12* **Log and audit** every tool call for compliance, debugging, or analytics

13* **Transform inputs and outputs** to sanitize data, inject credentials, or redirect file paths

14* **Require human approval** for sensitive actions like database writes or API calls

15* **Track session lifecycle** to manage state, clean up resources, or send notifications

16 

17This guide covers how hooks work, how to configure them, and provides examples for common patterns like blocking tools, modifying inputs, and forwarding notifications.

18 

19## How hooks work

20 

21<Steps>

22 <Step title="An event fires">

23 Something happens during agent execution and the SDK fires an event: a tool is about to be called (`PreToolUse`), a tool returned a result (`PostToolUse`), a subagent started or stopped, the agent is idle, or execution finished. See the [full list of events](#available-hooks).

24 </Step>

25 

26 <Step title="The SDK collects registered hooks">

27 The SDK checks for hooks registered for that event type. This includes callback hooks you pass in `options.hooks` and shell command hooks from settings files when the corresponding [`settingSources`](/en/agent-sdk/typescript#setting-source) or [`setting_sources`](/en/agent-sdk/python#setting-source) entry is enabled, which it is for default `query()` options.

28 </Step>

29 

30 <Step title="Matchers filter which hooks run">

31 If a hook has a [`matcher`](#matchers) pattern (like `"Write|Edit"`), the SDK tests it against the event's target (for example, the tool name). Hooks without a matcher run for every event of that type.

32 </Step>

33 

34 <Step title="Callback functions execute">

35 Each matching hook's [callback function](#callback-functions) receives input about what's happening: the tool name, its arguments, the session ID, and other event-specific details.

36 </Step>

37 

38 <Step title="Your callback returns a decision">

39 After performing any operations (logging, API calls, validation), your callback returns an [output object](#outputs) that tells the agent what to do: allow the operation, block it, modify the input, or inject context into the conversation.

40 </Step>

41</Steps>

42 

43The following example puts these steps together. It registers a `PreToolUse` hook (step 1) with a `"Write|Edit"` matcher (step 3) so the callback only fires for file-writing tools. When triggered, the callback receives the tool's input (step 4), checks if the file path targets a `.env` file, and returns `permissionDecision: "deny"` to block the operation (step 5):

44 

45<CodeGroup>

46 ```python Python theme={null}

47 import asyncio

48 from claude_agent_sdk import (

49 AssistantMessage,

50 ClaudeSDKClient,

51 ClaudeAgentOptions,

52 HookMatcher,

53 ResultMessage,

54 )

55 

56 

57 # Define a hook callback that receives tool call details

58 async def protect_env_files(input_data, tool_use_id, context):

59 # Extract the file path from the tool's input arguments

60 file_path = input_data["tool_input"].get("file_path", "")

61 file_name = file_path.split("/")[-1]

62 

63 # Block the operation if targeting a .env file

64 if file_name == ".env":

65 return {

66 "hookSpecificOutput": {

67 "hookEventName": input_data["hook_event_name"],

68 "permissionDecision": "deny",

69 "permissionDecisionReason": "Cannot modify .env files",

70 }

71 }

72 

73 # Return empty object to allow the operation

74 return {}

75 

76 

77 async def main():

78 options = ClaudeAgentOptions(

79 hooks={

80 # Register the hook for PreToolUse events

81 # The matcher filters to only Write and Edit tool calls

82 "PreToolUse": [HookMatcher(matcher="Write|Edit", hooks=[protect_env_files])]

83 }

84 )

85 

86 async with ClaudeSDKClient(options=options) as client:

87 await client.query("Update the database configuration")

88 async for message in client.receive_response():

89 # Filter for assistant and result messages

90 if isinstance(message, (AssistantMessage, ResultMessage)):

91 print(message)

92 

93 

94 asyncio.run(main())

95 ```

96 

97 ```typescript TypeScript theme={null}

98 import { query, HookCallback, PreToolUseHookInput } from "@anthropic-ai/claude-agent-sdk";

99 

100 // Define a hook callback with the HookCallback type

101 const protectEnvFiles: HookCallback = async (input, toolUseID, { signal }) => {

102 // Cast input to the specific hook type for type safety

103 const preInput = input as PreToolUseHookInput;

104 

105 // Cast tool_input to access its properties (typed as unknown in the SDK)

106 const toolInput = preInput.tool_input as Record<string, unknown>;

107 const filePath = toolInput?.file_path as string;

108 const fileName = filePath?.split("/").pop();

109 

110 // Block the operation if targeting a .env file

111 if (fileName === ".env") {

112 return {

113 hookSpecificOutput: {

114 hookEventName: preInput.hook_event_name,

115 permissionDecision: "deny",

116 permissionDecisionReason: "Cannot modify .env files"

117 }

118 };

119 }

120 

121 // Return empty object to allow the operation

122 return {};

123 };

124 

125 for await (const message of query({

126 prompt: "Update the database configuration",

127 options: {

128 hooks: {

129 // Register the hook for PreToolUse events

130 // The matcher filters to only Write and Edit tool calls

131 PreToolUse: [{ matcher: "Write|Edit", hooks: [protectEnvFiles] }]

132 }

133 }

134 })) {

135 // Filter for assistant and result messages

136 if (message.type === "assistant" || message.type === "result") {

137 console.log(message);

138 }

139 }

140 ```

141</CodeGroup>

142 

143## Available hooks

144 

145The SDK provides hooks for different stages of agent execution. Some hooks are available in both SDKs, while others are TypeScript-only.

146 

147| Hook Event | Python SDK | TypeScript SDK | What triggers it | Example use case |

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

149| `PreToolUse` | Yes | Yes | Tool call request (can block or modify) | Block dangerous shell commands |

150| `PostToolUse` | Yes | Yes | Tool execution result | Log all file changes to audit trail |

151| `PostToolUseFailure` | Yes | Yes | Tool execution failure | Handle or log tool errors |

152| `PostToolBatch` | No | Yes | A full batch of tool calls resolves, once per batch before the next model call | Inject conventions once for the whole batch |

153| `UserPromptSubmit` | Yes | Yes | User prompt submission | Inject additional context into prompts |

154| `Stop` | Yes | Yes | Agent execution stop | Save session state before exit |

155| `SubagentStart` | Yes | Yes | Subagent initialization | Track parallel task spawning |

156| `SubagentStop` | Yes | Yes | Subagent completion | Aggregate results from parallel tasks |

157| `PreCompact` | Yes | Yes | Conversation compaction request | Archive full transcript before summarizing |

158| `PermissionRequest` | Yes | Yes | Permission dialog would be displayed | Custom permission handling |

159| `SessionStart` | No | Yes | Session initialization | Initialize logging and telemetry |

160| `SessionEnd` | No | Yes | Session termination | Clean up temporary resources |

161| `Notification` | Yes | Yes | Agent status messages | Send agent status updates to Slack or PagerDuty |

162| `Setup` | No | Yes | Session setup/maintenance | Run initialization tasks |

163| `TeammateIdle` | No | Yes | Teammate becomes idle | Reassign work or notify |

164| `TaskCompleted` | No | Yes | Background task completes | Aggregate results from parallel tasks |

165| `ConfigChange` | No | Yes | Configuration file changes | Reload settings dynamically |

166| `WorktreeCreate` | No | Yes | Git worktree created | Track isolated workspaces |

167| `WorktreeRemove` | No | Yes | Git worktree removed | Clean up workspace resources |

168 

169## Configure hooks

170 

171To configure a hook, pass it in the `hooks` field of your agent options (`ClaudeAgentOptions` in Python, the `options` object in TypeScript):

172 

173<CodeGroup>

174 ```python Python theme={null}

175 options = ClaudeAgentOptions(

176 hooks={"PreToolUse": [HookMatcher(matcher="Bash", hooks=[my_callback])]}

177 )

178 

179 async with ClaudeSDKClient(options=options) as client:

180 await client.query("Your prompt")

181 async for message in client.receive_response():

182 print(message)

183 ```

184 

185 ```typescript TypeScript theme={null}

186 for await (const message of query({

187 prompt: "Your prompt",

188 options: {

189 hooks: {

190 PreToolUse: [{ matcher: "Bash", hooks: [myCallback] }]

191 }

192 }

193 })) {

194 console.log(message);

195 }

196 ```

197</CodeGroup>

198 

199The `hooks` option is a dictionary (Python) or object (TypeScript) where:

200 

201* **Keys** are [hook event names](#available-hooks) (e.g., `'PreToolUse'`, `'PostToolUse'`, `'Stop'`)

202* **Values** are arrays of [matchers](#matchers), each containing an optional filter pattern and your [callback functions](#callback-functions)

203 

204### Matchers

205 

206Use matchers to filter when your callbacks fire. The `matcher` field is a regex string that matches against a different value depending on the hook event type. For example, tool-based hooks match against the tool name, while `Notification` hooks match against the notification type. See the [Claude Code hooks reference](/en/hooks#matcher-patterns) for the full list of matcher values for each event type.

207 

208| Option | Type | Default | Description |

209| --------- | ---------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

210| `matcher` | `string` | `undefined` | Regex pattern matched against the event's filter field. For tool hooks, this is the tool name. Built-in tools include `Bash`, `Read`, `Write`, `Edit`, `Glob`, `Grep`, `WebFetch`, `Agent`, and others (see [Tool Input Types](/en/agent-sdk/typescript#tool-input-types) for the full list). MCP tools use the pattern `mcp__<server>__<action>`. |

211| `hooks` | `HookCallback[]` | - | Required. Array of callback functions to execute when the pattern matches |

212| `timeout` | `number` | `60` | Timeout in seconds |

213 

214Use the `matcher` pattern to target specific tools whenever possible. A matcher with `'Bash'` only runs for Bash commands, while omitting the pattern runs your callbacks for every occurrence of the event. Note that for tool-based hooks, matchers only filter by **tool name**, not by file paths or other arguments. To filter by file path, check `tool_input.file_path` inside your callback.

215 

216<Tip>

217 **Discovering tool names:** See [Tool Input Types](/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.

218 

219 **MCP tool naming:** MCP tools always start with `mcp__` followed by the server name and action: `mcp__<server>__<action>`. For example, if you configure a server named `playwright`, its tools will be named `mcp__playwright__browser_screenshot`, `mcp__playwright__browser_click`, etc. The server name comes from the key you use in the `mcpServers` configuration.

220</Tip>

221 

222### Callback functions

223 

224#### Inputs

225 

226Every hook callback receives three arguments:

227 

228* **Input data:** a typed object containing event details. Each hook type has its own input shape (for example, `PreToolUseHookInput` includes `tool_name` and `tool_input`, while `NotificationHookInput` includes `message`). See the full type definitions in the [TypeScript](/en/agent-sdk/typescript#hook-input) and [Python](/en/agent-sdk/python#hook-input) SDK references.

229 * All hook inputs share `session_id`, `cwd`, and `hook_event_name`.

230 * `agent_id` and `agent_type` are populated when the hook fires inside a subagent. In TypeScript, these are on the base hook input and available to all hook types. In Python, they are on `PreToolUse`, `PostToolUse`, and `PostToolUseFailure` only.

231* **Tool use ID** (`str | None` / `string | undefined`): correlates `PreToolUse` and `PostToolUse` events for the same tool call.

232* **Context:** in TypeScript, contains a `signal` property (`AbortSignal`) for cancellation. In Python, this argument is reserved for future use.

233 

234#### Outputs

235 

236Your callback returns an object with two categories of fields:

237 

238* **Top-level fields** control the conversation: `systemMessage` injects a message into the conversation visible to the model, and `continue` (`continue_` in Python) determines whether the agent keeps running after this hook.

239* **`hookSpecificOutput`** controls the current operation. The fields inside depend on the hook event type. For `PreToolUse` hooks, this is where you set `permissionDecision` (`"allow"`, `"deny"`, or `"ask"`), `permissionDecisionReason`, and `updatedInput`. In the TypeScript SDK, `permissionDecision` also accepts `"defer"` to end the query and [resume later](/en/hooks#defer-a-tool-call-for-later); this value is not available in the Python SDK. For `PostToolUse` hooks, you can set `additionalContext` to append information to the tool result.

240 

241Return `{}` to allow the operation without changes. SDK callback hooks use the same JSON output format as [Claude Code shell command hooks](/en/hooks#json-output), which documents every field and event-specific option. For the SDK type definitions, see the [TypeScript](/en/agent-sdk/typescript#sync-hook-json-output) and [Python](/en/agent-sdk/python#sync-hook-json-output) SDK references.

242 

243<Note>

244 When multiple hooks or permission rules apply, **deny** takes priority over **defer**, which takes priority over **ask**, which takes priority over **allow**. If any hook returns `deny`, the operation is blocked regardless of other hooks.

245</Note>

246 

247#### Asynchronous output

248 

249By default, the agent waits for your hook to return before proceeding. If your hook performs a side effect (logging, sending a webhook) and doesn't need to influence the agent's behavior, you can return an async output instead. This tells the agent to continue immediately without waiting for the hook to finish:

250 

251<CodeGroup>

252 ```python Python theme={null}

253 async def async_hook(input_data, tool_use_id, context):

254 # Start a background task, then return immediately

255 asyncio.create_task(send_to_logging_service(input_data))

256 return {"async_": True, "asyncTimeout": 30000}

257 ```

258 

259 ```typescript TypeScript theme={null}

260 const asyncHook: HookCallback = async (input, toolUseID, { signal }) => {

261 // Start a background task, then return immediately

262 sendToLoggingService(input).catch(console.error);

263 return { async: true, asyncTimeout: 30000 };

264 };

265 ```

266</CodeGroup>

267 

268| Field | Type | Description |

269| -------------- | -------- | -------------------------------------------------------------------------------------------------------------- |

270| `async` | `true` | Signals async mode. The agent proceeds without waiting. In Python, use `async_` to avoid the reserved keyword. |

271| `asyncTimeout` | `number` | Optional timeout in milliseconds for the background operation |

272 

273<Note>

274 Async outputs cannot block, modify, or inject context into the operation since the agent has already moved on. Use them only for side effects like logging, metrics, or notifications.

275</Note>

276 

277## Examples

278 

279### Modify tool input

280 

281This example intercepts Write tool calls and rewrites the `file_path` argument to prepend `/sandbox`, redirecting all file writes to a sandboxed directory. The callback returns `updatedInput` with the modified path and `permissionDecision: 'allow'` to auto-approve the rewritten operation:

282 

283<CodeGroup>

284 ```python Python theme={null}

285 async def redirect_to_sandbox(input_data, tool_use_id, context):

286 if input_data["hook_event_name"] != "PreToolUse":

287 return {}

288 

289 if input_data["tool_name"] == "Write":

290 original_path = input_data["tool_input"].get("file_path", "")

291 return {

292 "hookSpecificOutput": {

293 "hookEventName": input_data["hook_event_name"],

294 "permissionDecision": "allow",

295 "updatedInput": {

296 **input_data["tool_input"],

297 "file_path": f"/sandbox{original_path}",

298 },

299 }

300 }

301 return {}

302 ```

303 

304 ```typescript TypeScript theme={null}

305 const redirectToSandbox: HookCallback = async (input, toolUseID, { signal }) => {

306 if (input.hook_event_name !== "PreToolUse") return {};

307 

308 const preInput = input as PreToolUseHookInput;

309 const toolInput = preInput.tool_input as Record<string, unknown>;

310 if (preInput.tool_name === "Write") {

311 const originalPath = toolInput.file_path as string;

312 return {

313 hookSpecificOutput: {

314 hookEventName: preInput.hook_event_name,

315 permissionDecision: "allow",

316 updatedInput: {

317 ...toolInput,

318 file_path: `/sandbox${originalPath}`

319 }

320 }

321 };

322 }

323 return {};

324 };

325 ```

326</CodeGroup>

327 

328<Note>

329 When using `updatedInput`, you must also include `permissionDecision: 'allow'`. Always return a new object rather than mutating the original `tool_input`.

330</Note>

331 

332### Add context and block a tool

333 

334This example blocks any attempt to write to the `/etc` directory and uses two output fields together: `permissionDecision: 'deny'` stops the tool call, while `systemMessage` injects a reminder into the conversation so the agent receives context about why the operation was blocked and avoids retrying it:

335 

336<CodeGroup>

337 ```python Python theme={null}

338 async def block_etc_writes(input_data, tool_use_id, context):

339 file_path = input_data["tool_input"].get("file_path", "")

340 

341 if file_path.startswith("/etc"):

342 return {

343 # Top-level field: inject guidance into the conversation

344 "systemMessage": "Remember: system directories like /etc are protected.",

345 # hookSpecificOutput: block the operation

346 "hookSpecificOutput": {

347 "hookEventName": input_data["hook_event_name"],

348 "permissionDecision": "deny",

349 "permissionDecisionReason": "Writing to /etc is not allowed",

350 },

351 }

352 return {}

353 ```

354 

355 ```typescript TypeScript theme={null}

356 const blockEtcWrites: HookCallback = async (input, toolUseID, { signal }) => {

357 const preInput = input as PreToolUseHookInput;

358 const toolInput = preInput.tool_input as Record<string, unknown>;

359 const filePath = toolInput?.file_path as string;

360 

361 if (filePath?.startsWith("/etc")) {

362 return {

363 // Top-level field: inject guidance into the conversation

364 systemMessage: "Remember: system directories like /etc are protected.",

365 // hookSpecificOutput: block the operation

366 hookSpecificOutput: {

367 hookEventName: preInput.hook_event_name,

368 permissionDecision: "deny",

369 permissionDecisionReason: "Writing to /etc is not allowed"

370 }

371 };

372 }

373 return {};

374 };

375 ```

376</CodeGroup>

377 

378### Auto-approve specific tools

379 

380By default, the agent may prompt for permission before using certain tools. This example auto-approves read-only filesystem tools (Read, Glob, Grep) by returning `permissionDecision: 'allow'`, letting them run without user confirmation while leaving all other tools subject to normal permission checks:

381 

382<CodeGroup>

383 ```python Python theme={null}

384 async def auto_approve_read_only(input_data, tool_use_id, context):

385 if input_data["hook_event_name"] != "PreToolUse":

386 return {}

387 

388 read_only_tools = ["Read", "Glob", "Grep"]

389 if input_data["tool_name"] in read_only_tools:

390 return {

391 "hookSpecificOutput": {

392 "hookEventName": input_data["hook_event_name"],

393 "permissionDecision": "allow",

394 "permissionDecisionReason": "Read-only tool auto-approved",

395 }

396 }

397 return {}

398 ```

399 

400 ```typescript TypeScript theme={null}

401 const autoApproveReadOnly: HookCallback = async (input, toolUseID, { signal }) => {

402 if (input.hook_event_name !== "PreToolUse") return {};

403 

404 const preInput = input as PreToolUseHookInput;

405 const readOnlyTools = ["Read", "Glob", "Grep"];

406 if (readOnlyTools.includes(preInput.tool_name)) {

407 return {

408 hookSpecificOutput: {

409 hookEventName: preInput.hook_event_name,

410 permissionDecision: "allow",

411 permissionDecisionReason: "Read-only tool auto-approved"

412 }

413 };

414 }

415 return {};

416 };

417 ```

418</CodeGroup>

419 

420### Chain multiple hooks

421 

422Hooks execute in the order they appear in the array. Keep each hook focused on a single responsibility and chain multiple hooks for complex logic:

423 

424<CodeGroup>

425 ```python Python theme={null}

426 options = ClaudeAgentOptions(

427 hooks={

428 "PreToolUse": [

429 HookMatcher(hooks=[rate_limiter]), # First: check rate limits

430 HookMatcher(hooks=[authorization_check]), # Second: verify permissions

431 HookMatcher(hooks=[input_sanitizer]), # Third: sanitize inputs

432 HookMatcher(hooks=[audit_logger]), # Last: log the action

433 ]

434 }

435 )

436 ```

437 

438 ```typescript TypeScript theme={null}

439 const options = {

440 hooks: {

441 PreToolUse: [

442 { hooks: [rateLimiter] }, // First: check rate limits

443 { hooks: [authorizationCheck] }, // Second: verify permissions

444 { hooks: [inputSanitizer] }, // Third: sanitize inputs

445 { hooks: [auditLogger] } // Last: log the action

446 ]

447 }

448 };

449 ```

450</CodeGroup>

451 

452### Filter with regex matchers

453 

454Use regex patterns to match multiple tools. This example registers three matchers with different scopes: the first triggers `file_security_hook` only for file modification tools, the second triggers `mcp_audit_hook` for any MCP tool (tools whose names start with `mcp__`), and the third triggers `global_logger` for every tool call regardless of name:

455 

456<CodeGroup>

457 ```python Python theme={null}

458 options = ClaudeAgentOptions(

459 hooks={

460 "PreToolUse": [

461 # Match file modification tools

462 HookMatcher(matcher="Write|Edit|Delete", hooks=[file_security_hook]),

463 # Match all MCP tools

464 HookMatcher(matcher="^mcp__", hooks=[mcp_audit_hook]),

465 # Match everything (no matcher)

466 HookMatcher(hooks=[global_logger]),

467 ]

468 }

469 )

470 ```

471 

472 ```typescript TypeScript theme={null}

473 const options = {

474 hooks: {

475 PreToolUse: [

476 // Match file modification tools

477 { matcher: "Write|Edit|Delete", hooks: [fileSecurityHook] },

478 

479 // Match all MCP tools

480 { matcher: "^mcp__", hooks: [mcpAuditHook] },

481 

482 // Match everything (no matcher)

483 { hooks: [globalLogger] }

484 ]

485 }

486 };

487 ```

488</CodeGroup>

489 

490### Track subagent activity

491 

492Use `SubagentStop` hooks to monitor when subagents finish their work. See the full input type in the [TypeScript](/en/agent-sdk/typescript#hook-input) and [Python](/en/agent-sdk/python#hook-input) SDK references. This example logs a summary each time a subagent completes:

493 

494<CodeGroup>

495 ```python Python theme={null}

496 async def subagent_tracker(input_data, tool_use_id, context):

497 # Log subagent details when it finishes

498 print(f"[SUBAGENT] Completed: {input_data['agent_id']}")

499 print(f" Transcript: {input_data['agent_transcript_path']}")

500 print(f" Tool use ID: {tool_use_id}")

501 print(f" Stop hook active: {input_data.get('stop_hook_active')}")

502 return {}

503 

504 

505 options = ClaudeAgentOptions(

506 hooks={"SubagentStop": [HookMatcher(hooks=[subagent_tracker])]}

507 )

508 ```

509 

510 ```typescript TypeScript theme={null}

511 import { HookCallback, SubagentStopHookInput } from "@anthropic-ai/claude-agent-sdk";

512 

513 const subagentTracker: HookCallback = async (input, toolUseID, { signal }) => {

514 // Cast to SubagentStopHookInput to access subagent-specific fields

515 const subInput = input as SubagentStopHookInput;

516 

517 // Log subagent details when it finishes

518 console.log(`[SUBAGENT] Completed: ${subInput.agent_id}`);

519 console.log(` Transcript: ${subInput.agent_transcript_path}`);

520 console.log(` Tool use ID: ${toolUseID}`);

521 console.log(` Stop hook active: ${subInput.stop_hook_active}`);

522 return {};

523 };

524 

525 const options = {

526 hooks: {

527 SubagentStop: [{ hooks: [subagentTracker] }]

528 }

529 };

530 ```

531</CodeGroup>

532 

533### Make HTTP requests from hooks

534 

535Hooks can perform asynchronous operations like HTTP requests. Catch errors inside your hook instead of letting them propagate, since an unhandled exception can interrupt the agent.

536 

537This example sends a webhook after each tool completes, logging which tool ran and when. The hook catches errors so a failed webhook doesn't interrupt the agent:

538 

539<CodeGroup>

540 ```python Python theme={null}

541 import asyncio

542 import json

543 import urllib.request

544 from datetime import datetime

545 

546 

547 def _send_webhook(tool_name):

548 """Synchronous helper that POSTs tool usage data to an external webhook."""

549 data = json.dumps(

550 {

551 "tool": tool_name,

552 "timestamp": datetime.now().isoformat(),

553 }

554 ).encode()

555 req = urllib.request.Request(

556 "https://api.example.com/webhook",

557 data=data,

558 headers={"Content-Type": "application/json"},

559 method="POST",

560 )

561 urllib.request.urlopen(req)

562 

563 

564 async def webhook_notifier(input_data, tool_use_id, context):

565 # Only fire after a tool completes (PostToolUse), not before

566 if input_data["hook_event_name"] != "PostToolUse":

567 return {}

568 

569 try:

570 # Run the blocking HTTP call in a thread to avoid blocking the event loop

571 await asyncio.to_thread(_send_webhook, input_data["tool_name"])

572 except Exception as e:

573 # Log the error but don't raise. A failed webhook shouldn't stop the agent

574 print(f"Webhook request failed: {e}")

575 

576 return {}

577 ```

578 

579 ```typescript TypeScript theme={null}

580 import { query, HookCallback, PostToolUseHookInput } from "@anthropic-ai/claude-agent-sdk";

581 

582 const webhookNotifier: HookCallback = async (input, toolUseID, { signal }) => {

583 // Only fire after a tool completes (PostToolUse), not before

584 if (input.hook_event_name !== "PostToolUse") return {};

585 

586 try {

587 await fetch("https://api.example.com/webhook", {

588 method: "POST",

589 headers: { "Content-Type": "application/json" },

590 body: JSON.stringify({

591 tool: (input as PostToolUseHookInput).tool_name,

592 timestamp: new Date().toISOString()

593 }),

594 // Pass signal so the request cancels if the hook times out

595 signal

596 });

597 } catch (error) {

598 // Handle cancellation separately from other errors

599 if (error instanceof Error && error.name === "AbortError") {

600 console.log("Webhook request cancelled");

601 }

602 // Don't re-throw. A failed webhook shouldn't stop the agent

603 }

604 

605 return {};

606 };

607 

608 // Register as a PostToolUse hook

609 for await (const message of query({

610 prompt: "Refactor the auth module",

611 options: {

612 hooks: {

613 PostToolUse: [{ hooks: [webhookNotifier] }]

614 }

615 }

616 })) {

617 console.log(message);

618 }

619 ```

620</CodeGroup>

621 

622### Forward notifications to Slack

623 

624Use `Notification` hooks to receive system notifications from the agent and forward them to external services. Notifications fire for specific event types: `permission_prompt` (Claude needs permission), `idle_prompt` (Claude is waiting for input), `auth_success` (authentication completed), and `elicitation_dialog` (Claude is prompting the user). Each notification includes a `message` field with a human-readable description and optionally a `title`.

625 

626This example forwards every notification to a Slack channel. It requires a [Slack incoming webhook URL](https://api.slack.com/messaging/webhooks), which you create by adding an app to your Slack workspace and enabling incoming webhooks:

627 

628<CodeGroup>

629 ```python Python theme={null}

630 import asyncio

631 import json

632 import urllib.request

633 

634 from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, HookMatcher

635 

636 

637 def _send_slack_notification(message):

638 """Synchronous helper that sends a message to Slack via incoming webhook."""

639 data = json.dumps({"text": f"Agent status: {message}"}).encode()

640 req = urllib.request.Request(

641 "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",

642 data=data,

643 headers={"Content-Type": "application/json"},

644 method="POST",

645 )

646 urllib.request.urlopen(req)

647 

648 

649 async def notification_handler(input_data, tool_use_id, context):

650 try:

651 # Run the blocking HTTP call in a thread to avoid blocking the event loop

652 await asyncio.to_thread(_send_slack_notification, input_data.get("message", ""))

653 except Exception as e:

654 print(f"Failed to send notification: {e}")

655 

656 # Return empty object. Notification hooks don't modify agent behavior

657 return {}

658 

659 

660 async def main():

661 options = ClaudeAgentOptions(

662 hooks={

663 # Register the hook for Notification events (no matcher needed)

664 "Notification": [HookMatcher(hooks=[notification_handler])],

665 },

666 )

667 

668 async with ClaudeSDKClient(options=options) as client:

669 await client.query("Analyze this codebase")

670 async for message in client.receive_response():

671 print(message)

672 

673 

674 asyncio.run(main())

675 ```

676 

677 ```typescript TypeScript theme={null}

678 import { query, HookCallback, NotificationHookInput } from "@anthropic-ai/claude-agent-sdk";

679 

680 // Define a hook callback that sends notifications to Slack

681 const notificationHandler: HookCallback = async (input, toolUseID, { signal }) => {

682 // Cast to NotificationHookInput to access the message field

683 const notification = input as NotificationHookInput;

684 

685 try {

686 // POST the notification message to a Slack incoming webhook

687 await fetch("https://hooks.slack.com/services/YOUR/WEBHOOK/URL", {

688 method: "POST",

689 headers: { "Content-Type": "application/json" },

690 body: JSON.stringify({

691 text: `Agent status: ${notification.message}`

692 }),

693 // Pass signal so the request cancels if the hook times out

694 signal

695 });

696 } catch (error) {

697 if (error instanceof Error && error.name === "AbortError") {

698 console.log("Notification cancelled");

699 } else {

700 console.error("Failed to send notification:", error);

701 }

702 }

703 

704 // Return empty object. Notification hooks don't modify agent behavior

705 return {};

706 };

707 

708 // Register the hook for Notification events (no matcher needed)

709 for await (const message of query({

710 prompt: "Analyze this codebase",

711 options: {

712 hooks: {

713 Notification: [{ hooks: [notificationHandler] }]

714 }

715 }

716 })) {

717 console.log(message);

718 }

719 ```

720</CodeGroup>

721 

722## Fix common issues

723 

724### Hook not firing

725 

726* Verify the hook event name is correct and case-sensitive (`PreToolUse`, not `preToolUse`)

727* Check that your matcher pattern matches the tool name exactly

728* Ensure the hook is under the correct event type in `options.hooks`

729* For non-tool hooks like `Stop` and `SubagentStop`, matchers match against different fields (see [matcher patterns](/en/hooks#matcher-patterns))

730* Hooks may not fire when the agent hits the [`max_turns`](/en/agent-sdk/python#claude-agent-options) limit because the session ends before hooks can execute

731 

732### Matcher not filtering as expected

733 

734Matchers only match **tool names**, not file paths or other arguments. To filter by file path, check `tool_input.file_path` inside your hook:

735 

736```typescript theme={null}

737const myHook: HookCallback = async (input, toolUseID, { signal }) => {

738 const preInput = input as PreToolUseHookInput;

739 const toolInput = preInput.tool_input as Record<string, unknown>;

740 const filePath = toolInput?.file_path as string;

741 if (!filePath?.endsWith(".md")) return {}; // Skip non-markdown files

742 // Process markdown files...

743 return {};

744};

745```

746 

747### Hook timeout

748 

749* Increase the `timeout` value in the `HookMatcher` configuration

750* Use the `AbortSignal` from the third callback argument to handle cancellation gracefully in TypeScript

751 

752### Tool blocked unexpectedly

753 

754* Check all `PreToolUse` hooks for `permissionDecision: 'deny'` returns

755* Add logging to your hooks to see what `permissionDecisionReason` they're returning

756* Verify matcher patterns aren't too broad (an empty matcher matches all tools)

757 

758### Modified input not applied

759 

760* Ensure `updatedInput` is inside `hookSpecificOutput`, not at the top level:

761 

762 ```typescript theme={null}

763 return {

764 hookSpecificOutput: {

765 hookEventName: "PreToolUse",

766 permissionDecision: "allow",

767 updatedInput: { command: "new command" }

768 }

769 };

770 ```

771 

772* You must also return `permissionDecision: 'allow'` for the input modification to take effect

773 

774* Include `hookEventName` in `hookSpecificOutput` to identify which hook type the output is for

775 

776### Session hooks not available in Python

777 

778`SessionStart` and `SessionEnd` can be registered as SDK callback hooks in TypeScript, but are not available in the Python SDK (`HookEvent` omits them). In Python, they are only available as [shell command hooks](/en/hooks#hook-events) defined in settings files (for example, `.claude/settings.json`). To load shell command hooks from your SDK application, include the appropriate setting source with [`setting_sources`](/en/agent-sdk/python#setting-source) or [`settingSources`](/en/agent-sdk/typescript#setting-source):

779 

780<CodeGroup>

781 ```python Python theme={null}

782 options = ClaudeAgentOptions(

783 setting_sources=["project"], # Loads .claude/settings.json including hooks

784 )

785 ```

786 

787 ```typescript TypeScript theme={null}

788 const options = {

789 settingSources: ["project"] // Loads .claude/settings.json including hooks

790 };

791 ```

792</CodeGroup>

793 

794To run initialization logic as a Python SDK callback instead, use the first message from `client.receive_response()` as your trigger.

795 

796### Subagent permission prompts multiplying

797 

798When spawning multiple subagents, each one may request permissions separately. Subagents do not automatically inherit parent agent permissions. To avoid repeated prompts, use `PreToolUse` hooks to auto-approve specific tools, or configure permission rules that apply to subagent sessions.

799 

800### Recursive hook loops with subagents

801 

802A `UserPromptSubmit` hook that spawns subagents can create infinite loops if those subagents trigger the same hook. To prevent this:

803 

804* Check for a subagent indicator in the hook input before spawning

805* Use a shared variable or session state to track whether you're already inside a subagent

806* Scope hooks to only run for the top-level agent session

807 

808### systemMessage not appearing in output

809 

810The `systemMessage` field adds context to the conversation that the model sees, but it may not appear in all SDK output modes. If you need to surface hook decisions to your application, log them separately or use a dedicated output channel.

811 

812## Related resources

813 

814* [Claude Code hooks reference](/en/hooks): full JSON input/output schemas, event documentation, and matcher patterns

815* [Claude Code hooks guide](/en/hooks-guide): shell command hook examples and walkthroughs

816* [TypeScript SDK reference](/en/agent-sdk/typescript): hook types, input/output definitions, and configuration options

817* [Python SDK reference](/en/agent-sdk/python): hook types, input/output definitions, and configuration options

818* [Permissions](/en/agent-sdk/permissions): control what your agent can do

819* [Custom tools](/en/agent-sdk/custom-tools): build tools to extend agent capabilities

agent-sdk/hosting.md +142 −0 added

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# Hosting the Agent SDK

6 

7> Deploy and host Claude Agent SDK in production environments

8 

9The Claude Agent SDK differs from traditional stateless LLM APIs in that it maintains conversational state and executes commands in a persistent environment. This guide covers the architecture, hosting considerations, and best practices for deploying SDK-based agents in production.

10 

11<Info>

12 For security hardening beyond basic sandboxing (including network controls, credential management, and isolation options), see [Secure Deployment](/en/agent-sdk/secure-deployment).

13</Info>

14 

15## Hosting Requirements

16 

17### Container-Based Sandboxing

18 

19For security and isolation, the SDK should run inside a sandboxed container environment. This provides process isolation, resource limits, network control, and ephemeral filesystems.

20 

21The SDK also supports [programmatic sandbox configuration](/en/agent-sdk/typescript#sandbox-settings) for command execution.

22 

23### System Requirements

24 

25Each SDK instance requires:

26 

27* **Runtime dependencies**

28 * Python 3.10+ for the Python SDK, or Node.js 18+ for the TypeScript SDK

29 * Both SDK packages bundle a native Claude Code binary for the host platform, so no separate Claude Code or Node.js install is needed for the spawned CLI

30 

31* **Resource allocation**

32 * Recommended: 1GiB RAM, 5GiB of disk, and 1 CPU (vary this based on your task as needed)

33 

34* **Network access**

35 * Outbound HTTPS to `api.anthropic.com`

36 * Optional: Access to MCP servers or external tools

37 

38## Understanding the SDK Architecture

39 

40Unlike stateless API calls, the Claude Agent SDK operates as a **long-running process** that:

41 

42* **Executes commands** in a persistent shell environment

43* **Manages file operations** within a working directory

44* **Handles tool execution** with context from previous interactions

45 

46## Sandbox Provider Options

47 

48Several providers specialize in secure container environments for AI code execution:

49 

50* **[Modal Sandbox](https://modal.com/docs/guide/sandbox)** - [demo implementation](https://modal.com/docs/examples/claude-slack-gif-creator)

51* **[Cloudflare Sandboxes](https://github.com/cloudflare/sandbox-sdk)**

52* **[Daytona](https://www.daytona.io/)**

53* **[E2B](https://e2b.dev/)**

54* **[Fly Machines](https://fly.io/docs/machines/)**

55* **[Vercel Sandbox](https://vercel.com/docs/functions/sandbox)**

56 

57For self-hosted options (Docker, gVisor, Firecracker) and detailed isolation configuration, see [Isolation Technologies](/en/agent-sdk/secure-deployment#isolation-technologies).

58 

59## Production Deployment Patterns

60 

61### Pattern 1: Ephemeral Sessions

62 

63Create a new container for each user task, then destroy it when complete.

64 

65Best for one-off tasks, the user may still interact with the AI while the task is completing, but once completed the container is destroyed.

66 

67**Examples:**

68 

69* Bug Investigation & Fix: Debug and resolve a specific issue with relevant context

70* Invoice Processing: Extract and structure data from receipts/invoices for accounting systems

71* Translation Tasks: Translate documents or content batches between languages

72* Image/Video Processing: Apply transformations, optimizations, or extract metadata from media files

73 

74### Pattern 2: Long-Running Sessions

75 

76Maintain persistent container instances for long running tasks. Often times running *multiple* Claude Agent processes inside of the container based on demand.

77 

78Best for proactive agents that take action without the users input, agents that serve content or agents that process high amounts of messages.

79 

80**Examples:**

81 

82* Email Agent: Monitors incoming emails and autonomously triages, responds, or takes actions based on content

83* Site Builder: Hosts custom websites per user with live editing capabilities served through container ports

84* High-Frequency Chat Bots: Handles continuous message streams from platforms like Slack where rapid response times are critical

85 

86### Pattern 3: Hybrid Sessions

87 

88Ephemeral containers that are hydrated with history and state, possibly from a database or from the SDK's session resumption features.

89 

90Best for containers with intermittent interaction from the user that kicks off work and spins down when the work is completed but can be continued.

91 

92**Examples:**

93 

94* Personal Project Manager: Helps manage ongoing projects with intermittent check-ins, maintains context of tasks, decisions, and progress

95* Deep Research: Conducts multi-hour research tasks, saves findings and resumes investigation when user returns

96* Customer Support Agent: Handles support tickets that span multiple interactions, loads ticket history and customer context

97 

98### Pattern 4: Single Containers

99 

100Run multiple Claude Agent SDK processes in one global container.

101 

102Best for agents that must collaborate closely together. This is likely the least popular pattern because you will have to prevent agents from overwriting each other.

103 

104**Examples:**

105 

106* **Simulations**: Agents that interact with each other in simulations such as video games.

107 

108## FAQ

109 

110### How do I communicate with my sandboxes?

111 

112When hosting in containers, expose ports to communicate with your SDK instances. Your application can expose HTTP/WebSocket endpoints for external clients while the SDK runs internally within the container.

113 

114### What is the cost of hosting a container?

115 

116The dominant cost of serving agents is the tokens; containers vary based on what you provision, but a minimum cost is roughly 5 cents per hour running.

117 

118### When should I shut down idle containers vs. keeping them warm?

119 

120This is likely provider dependent, different sandbox providers will let you set different criteria for idle timeouts after which a sandbox might spin down.

121You will want to tune this timeout based on how frequent you think user response might be.

122 

123### How often should I update the Claude Code CLI?

124 

125The Claude Code CLI is versioned with semver, so any breaking changes will be versioned.

126 

127### How do I monitor container health and agent performance?

128 

129Since containers are just servers the same logging infrastructure you use for the backend will work for containers.

130 

131### How long can an agent session run before timing out?

132 

133An agent session will not timeout, but consider setting a 'maxTurns' property to prevent Claude from getting stuck in a loop.

134 

135## Next Steps

136 

137* [Secure Deployment](/en/agent-sdk/secure-deployment) - Network controls, credential management, and isolation hardening

138* [TypeScript SDK - Sandbox Settings](/en/agent-sdk/typescript#sandbox-settings) - Configure sandbox programmatically

139* [Sessions Guide](/en/agent-sdk/sessions) - Learn about session management

140* [Permissions](/en/agent-sdk/permissions) - Configure tool permissions

141* [Cost Tracking](/en/agent-sdk/cost-tracking) - Monitor API usage

142* [MCP Integration](/en/agent-sdk/mcp) - Extend with custom tools

agent-sdk/mcp.md +768 −0 added

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# Connect to external tools with MCP

6 

7> Configure MCP servers to extend your agent with external tools. Covers transport types, tool search for large tool sets, authentication, and error handling.

8 

9The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro) is an open standard for connecting AI agents to external tools and data sources. With MCP, your agent can query databases, integrate with APIs like Slack and GitHub, and connect to other services without writing custom tool implementations.

10 

11MCP servers can run as local processes, connect over HTTP, or execute directly within your SDK application.

12 

13## Quickstart

14 

15This example connects to the [Claude Code documentation](https://code.claude.com/docs) MCP server using [HTTP transport](#httpsse-servers) and uses [`allowedTools`](#allow-mcp-tools) with a wildcard to permit all tools from the server.

16 

17<CodeGroup>

18 ```typescript TypeScript theme={null}

19 import { query } from "@anthropic-ai/claude-agent-sdk";

20 

21 for await (const message of query({

22 prompt: "Use the docs MCP server to explain what hooks are in Claude Code",

23 options: {

24 mcpServers: {

25 "claude-code-docs": {

26 type: "http",

27 url: "https://code.claude.com/docs/mcp"

28 }

29 },

30 allowedTools: ["mcp__claude-code-docs__*"]

31 }

32 })) {

33 if (message.type === "result" && message.subtype === "success") {

34 console.log(message.result);

35 }

36 }

37 ```

38 

39 ```python Python theme={null}

40 import asyncio

41 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

42 

43 

44 async def main():

45 options = ClaudeAgentOptions(

46 mcp_servers={

47 "claude-code-docs": {

48 "type": "http",

49 "url": "https://code.claude.com/docs/mcp",

50 }

51 },

52 allowed_tools=["mcp__claude-code-docs__*"],

53 )

54 

55 async for message in query(

56 prompt="Use the docs MCP server to explain what hooks are in Claude Code",

57 options=options,

58 ):

59 if isinstance(message, ResultMessage) and message.subtype == "success":

60 print(message.result)

61 

62 

63 asyncio.run(main())

64 ```

65</CodeGroup>

66 

67The agent connects to the documentation server, searches for information about hooks, and returns the results.

68 

69## Add an MCP server

70 

71You can configure MCP servers in code when calling `query()`, or in a `.mcp.json` file loaded via [`settingSources`](#from-a-config-file).

72 

73### In code

74 

75Pass MCP servers directly in the `mcpServers` option:

76 

77<CodeGroup>

78 ```typescript TypeScript theme={null}

79 import { query } from "@anthropic-ai/claude-agent-sdk";

80 

81 for await (const message of query({

82 prompt: "List files in my project",

83 options: {

84 mcpServers: {

85 filesystem: {

86 command: "npx",

87 args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]

88 }

89 },

90 allowedTools: ["mcp__filesystem__*"]

91 }

92 })) {

93 if (message.type === "result" && message.subtype === "success") {

94 console.log(message.result);

95 }

96 }

97 ```

98 

99 ```python Python theme={null}

100 import asyncio

101 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

102 

103 

104 async def main():

105 options = ClaudeAgentOptions(

106 mcp_servers={

107 "filesystem": {

108 "command": "npx",

109 "args": [

110 "-y",

111 "@modelcontextprotocol/server-filesystem",

112 "/Users/me/projects",

113 ],

114 }

115 },

116 allowed_tools=["mcp__filesystem__*"],

117 )

118 

119 async for message in query(prompt="List files in my project", options=options):

120 if isinstance(message, ResultMessage) and message.subtype == "success":

121 print(message.result)

122 

123 

124 asyncio.run(main())

125 ```

126</CodeGroup>

127 

128### From a config file

129 

130Create a `.mcp.json` file at your project root. The file is picked up when the `project` setting source is enabled, which it is for default `query()` options. If you set `settingSources` explicitly, include `"project"` for this file to load:

131 

132```json theme={null}

133{

134 "mcpServers": {

135 "filesystem": {

136 "command": "npx",

137 "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]

138 }

139 }

140}

141```

142 

143## Allow MCP tools

144 

145MCP tools require explicit permission before Claude can use them. Without permission, Claude will see that tools are available but won't be able to call them.

146 

147### Tool naming convention

148 

149MCP tools follow the naming pattern `mcp__<server-name>__<tool-name>`. For example, a GitHub server named `"github"` with a `list_issues` tool becomes `mcp__github__list_issues`.

150 

151### Grant access with allowedTools

152 

153Use `allowedTools` to specify which MCP tools Claude can use:

154 

155```typescript hidelines={1,-1} theme={null}

156const _ = {

157 options: {

158 mcpServers: {

159 // your servers

160 },

161 allowedTools: [

162 "mcp__github__*", // All tools from the github server

163 "mcp__db__query", // Only the query tool from db server

164 "mcp__slack__send_message" // Only send_message from slack server

165 ]

166 }

167};

168```

169 

170Wildcards (`*`) let you allow all tools from a server without listing each one individually.

171 

172<Note>

173 **Prefer `allowedTools` over permission modes for MCP access.** `permissionMode: "acceptEdits"` does not auto-approve MCP tools (only file edits and filesystem Bash commands). `permissionMode: "bypassPermissions"` does auto-approve MCP tools but also disables all other safety prompts, which is broader than necessary. A wildcard in `allowedTools` grants exactly the MCP server you want and nothing more. See [Permission modes](/en/agent-sdk/permissions#permission-modes) for a full comparison.

174</Note>

175 

176### Discover available tools

177 

178To see what tools an MCP server provides, check the server's documentation or connect to the server and inspect the `system` init message:

179 

180```typescript theme={null}

181for await (const message of query({ prompt: "...", options })) {

182 if (message.type === "system" && message.subtype === "init") {

183 console.log("Available MCP tools:", message.mcp_servers);

184 }

185}

186```

187 

188## Transport types

189 

190MCP servers communicate with your agent using different transport protocols. Check the server's documentation to see which transport it supports:

191 

192* If the docs give you a **command to run** (like `npx @modelcontextprotocol/server-github`), use stdio

193* If the docs give you a **URL**, use HTTP or SSE

194* If you're building your own tools in code, use an SDK MCP server

195 

196### stdio servers

197 

198Local processes that communicate via stdin/stdout. Use this for MCP servers you run on the same machine:

199 

200<Tabs>

201 <Tab title="In code">

202 <CodeGroup>

203 ```typescript TypeScript hidelines={1,-1} theme={null}

204 const _ = {

205 options: {

206 mcpServers: {

207 github: {

208 command: "npx",

209 args: ["-y", "@modelcontextprotocol/server-github"],

210 env: {

211 GITHUB_TOKEN: process.env.GITHUB_TOKEN

212 }

213 }

214 },

215 allowedTools: ["mcp__github__list_issues", "mcp__github__search_issues"]

216 }

217 };

218 ```

219 

220 ```python Python theme={null}

221 options = ClaudeAgentOptions(

222 mcp_servers={

223 "github": {

224 "command": "npx",

225 "args": ["-y", "@modelcontextprotocol/server-github"],

226 "env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},

227 }

228 },

229 allowed_tools=["mcp__github__list_issues", "mcp__github__search_issues"],

230 )

231 ```

232 </CodeGroup>

233 </Tab>

234 

235 <Tab title=".mcp.json">

236 ```json theme={null}

237 {

238 "mcpServers": {

239 "github": {

240 "command": "npx",

241 "args": ["-y", "@modelcontextprotocol/server-github"],

242 "env": {

243 "GITHUB_TOKEN": "${GITHUB_TOKEN}"

244 }

245 }

246 }

247 }

248 ```

249 </Tab>

250</Tabs>

251 

252### HTTP/SSE servers

253 

254Use HTTP or SSE for cloud-hosted MCP servers and remote APIs:

255 

256<Tabs>

257 <Tab title="In code">

258 <CodeGroup>

259 ```typescript TypeScript hidelines={1,-1} theme={null}

260 const _ = {

261 options: {

262 mcpServers: {

263 "remote-api": {

264 type: "sse",

265 url: "https://api.example.com/mcp/sse",

266 headers: {

267 Authorization: `Bearer ${process.env.API_TOKEN}`

268 }

269 }

270 },

271 allowedTools: ["mcp__remote-api__*"]

272 }

273 };

274 ```

275 

276 ```python Python theme={null}

277 options = ClaudeAgentOptions(

278 mcp_servers={

279 "remote-api": {

280 "type": "sse",

281 "url": "https://api.example.com/mcp/sse",

282 "headers": {"Authorization": f"Bearer {os.environ['API_TOKEN']}"},

283 }

284 },

285 allowed_tools=["mcp__remote-api__*"],

286 )

287 ```

288 </CodeGroup>

289 </Tab>

290 

291 <Tab title=".mcp.json">

292 ```json theme={null}

293 {

294 "mcpServers": {

295 "remote-api": {

296 "type": "sse",

297 "url": "https://api.example.com/mcp/sse",

298 "headers": {

299 "Authorization": "Bearer ${API_TOKEN}"

300 }

301 }

302 }

303 }

304 ```

305 </Tab>

306</Tabs>

307 

308For HTTP (non-streaming), use `"type": "http"` instead.

309 

310### SDK MCP servers

311 

312Define custom tools directly in your application code instead of running a separate server process. See the [custom tools guide](/en/agent-sdk/custom-tools) for implementation details.

313 

314## MCP tool search

315 

316When you have many MCP tools configured, tool definitions can consume a significant portion of your context window. Tool search solves this by withholding tool definitions from context and loading only the ones Claude needs for each turn.

317 

318Tool search is enabled by default. See [Tool search](/en/agent-sdk/tool-search) for configuration options and details.

319 

320For more detail, including best practices and using tool search with custom SDK tools, see the [tool search guide](/en/agent-sdk/tool-search).

321 

322## Authentication

323 

324Most MCP servers require authentication to access external services. Pass credentials through environment variables in the server configuration.

325 

326### Pass credentials via environment variables

327 

328Use the `env` field to pass API keys, tokens, and other credentials to the MCP server:

329 

330<Tabs>

331 <Tab title="In code">

332 <CodeGroup>

333 ```typescript TypeScript hidelines={1,-1} theme={null}

334 const _ = {

335 options: {

336 mcpServers: {

337 github: {

338 command: "npx",

339 args: ["-y", "@modelcontextprotocol/server-github"],

340 env: {

341 GITHUB_TOKEN: process.env.GITHUB_TOKEN

342 }

343 }

344 },

345 allowedTools: ["mcp__github__list_issues"]

346 }

347 };

348 ```

349 

350 ```python Python theme={null}

351 options = ClaudeAgentOptions(

352 mcp_servers={

353 "github": {

354 "command": "npx",

355 "args": ["-y", "@modelcontextprotocol/server-github"],

356 "env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},

357 }

358 },

359 allowed_tools=["mcp__github__list_issues"],

360 )

361 ```

362 </CodeGroup>

363 </Tab>

364 

365 <Tab title=".mcp.json">

366 ```json theme={null}

367 {

368 "mcpServers": {

369 "github": {

370 "command": "npx",

371 "args": ["-y", "@modelcontextprotocol/server-github"],

372 "env": {

373 "GITHUB_TOKEN": "${GITHUB_TOKEN}"

374 }

375 }

376 }

377 }

378 ```

379 

380 The `${GITHUB_TOKEN}` syntax expands environment variables at runtime.

381 </Tab>

382</Tabs>

383 

384See [List issues from a repository](#list-issues-from-a-repository) for a complete working example with debug logging.

385 

386### HTTP headers for remote servers

387 

388For HTTP and SSE servers, pass authentication headers directly in the server configuration:

389 

390<Tabs>

391 <Tab title="In code">

392 <CodeGroup>

393 ```typescript TypeScript hidelines={1,-1} theme={null}

394 const _ = {

395 options: {

396 mcpServers: {

397 "secure-api": {

398 type: "http",

399 url: "https://api.example.com/mcp",

400 headers: {

401 Authorization: `Bearer ${process.env.API_TOKEN}`

402 }

403 }

404 },

405 allowedTools: ["mcp__secure-api__*"]

406 }

407 };

408 ```

409 

410 ```python Python theme={null}

411 options = ClaudeAgentOptions(

412 mcp_servers={

413 "secure-api": {

414 "type": "http",

415 "url": "https://api.example.com/mcp",

416 "headers": {"Authorization": f"Bearer {os.environ['API_TOKEN']}"},

417 }

418 },

419 allowed_tools=["mcp__secure-api__*"],

420 )

421 ```

422 </CodeGroup>

423 </Tab>

424 

425 <Tab title=".mcp.json">

426 ```json theme={null}

427 {

428 "mcpServers": {

429 "secure-api": {

430 "type": "http",

431 "url": "https://api.example.com/mcp",

432 "headers": {

433 "Authorization": "Bearer ${API_TOKEN}"

434 }

435 }

436 }

437 }

438 ```

439 

440 The `${API_TOKEN}` syntax expands environment variables at runtime.

441 </Tab>

442</Tabs>

443 

444### OAuth2 authentication

445 

446The [MCP specification supports OAuth 2.1](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization) for authorization. The SDK doesn't handle OAuth flows automatically, but you can pass access tokens via headers after completing the OAuth flow in your application:

447 

448<CodeGroup>

449 ```typescript TypeScript theme={null}

450 // After completing OAuth flow in your app

451 const accessToken = await getAccessTokenFromOAuthFlow();

452 

453 const options = {

454 mcpServers: {

455 "oauth-api": {

456 type: "http",

457 url: "https://api.example.com/mcp",

458 headers: {

459 Authorization: `Bearer ${accessToken}`

460 }

461 }

462 },

463 allowedTools: ["mcp__oauth-api__*"]

464 };

465 ```

466 

467 ```python Python theme={null}

468 # After completing OAuth flow in your app

469 access_token = await get_access_token_from_oauth_flow()

470 

471 options = ClaudeAgentOptions(

472 mcp_servers={

473 "oauth-api": {

474 "type": "http",

475 "url": "https://api.example.com/mcp",

476 "headers": {"Authorization": f"Bearer {access_token}"},

477 }

478 },

479 allowed_tools=["mcp__oauth-api__*"],

480 )

481 ```

482</CodeGroup>

483 

484## Examples

485 

486### List issues from a repository

487 

488This example connects to the [GitHub MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/github) to list recent issues. The example includes debug logging to verify the MCP connection and tool calls.

489 

490Before running, create a [GitHub personal access token](https://github.com/settings/tokens) with `repo` scope and set it as an environment variable:

491 

492```bash theme={null}

493export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx

494```

495 

496<CodeGroup>

497 ```typescript TypeScript theme={null}

498 import { query } from "@anthropic-ai/claude-agent-sdk";

499 

500 for await (const message of query({

501 prompt: "List the 3 most recent issues in anthropics/claude-code",

502 options: {

503 mcpServers: {

504 github: {

505 command: "npx",

506 args: ["-y", "@modelcontextprotocol/server-github"],

507 env: {

508 GITHUB_TOKEN: process.env.GITHUB_TOKEN

509 }

510 }

511 },

512 allowedTools: ["mcp__github__list_issues"]

513 }

514 })) {

515 // Verify MCP server connected successfully

516 if (message.type === "system" && message.subtype === "init") {

517 console.log("MCP servers:", message.mcp_servers);

518 }

519 

520 // Log when Claude calls an MCP tool

521 if (message.type === "assistant") {

522 for (const block of message.message.content) {

523 if (block.type === "tool_use" && block.name.startsWith("mcp__")) {

524 console.log("MCP tool called:", block.name);

525 }

526 }

527 }

528 

529 // Print the final result

530 if (message.type === "result" && message.subtype === "success") {

531 console.log(message.result);

532 }

533 }

534 ```

535 

536 ```python Python theme={null}

537 import asyncio

538 import os

539 from claude_agent_sdk import (

540 query,

541 ClaudeAgentOptions,

542 ResultMessage,

543 SystemMessage,

544 AssistantMessage,

545 )

546 

547 

548 async def main():

549 options = ClaudeAgentOptions(

550 mcp_servers={

551 "github": {

552 "command": "npx",

553 "args": ["-y", "@modelcontextprotocol/server-github"],

554 "env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},

555 }

556 },

557 allowed_tools=["mcp__github__list_issues"],

558 )

559 

560 async for message in query(

561 prompt="List the 3 most recent issues in anthropics/claude-code",

562 options=options,

563 ):

564 # Verify MCP server connected successfully

565 if isinstance(message, SystemMessage) and message.subtype == "init":

566 print("MCP servers:", message.data.get("mcp_servers"))

567 

568 # Log when Claude calls an MCP tool

569 if isinstance(message, AssistantMessage):

570 for block in message.content:

571 if hasattr(block, "name") and block.name.startswith("mcp__"):

572 print("MCP tool called:", block.name)

573 

574 # Print the final result

575 if isinstance(message, ResultMessage) and message.subtype == "success":

576 print(message.result)

577 

578 

579 asyncio.run(main())

580 ```

581</CodeGroup>

582 

583### Query a database

584 

585This example uses the [Postgres MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/postgres) to query a database. The connection string is passed as an argument to the server. The agent automatically discovers the database schema, writes the SQL query, and returns the results:

586 

587<CodeGroup>

588 ```typescript TypeScript theme={null}

589 import { query } from "@anthropic-ai/claude-agent-sdk";

590 

591 // Connection string from environment variable

592 const connectionString = process.env.DATABASE_URL;

593 

594 for await (const message of query({

595 // Natural language query - Claude writes the SQL

596 prompt: "How many users signed up last week? Break it down by day.",

597 options: {

598 mcpServers: {

599 postgres: {

600 command: "npx",

601 // Pass connection string as argument to the server

602 args: ["-y", "@modelcontextprotocol/server-postgres", connectionString]

603 }

604 },

605 // Allow only read queries, not writes

606 allowedTools: ["mcp__postgres__query"]

607 }

608 })) {

609 if (message.type === "result" && message.subtype === "success") {

610 console.log(message.result);

611 }

612 }

613 ```

614 

615 ```python Python theme={null}

616 import asyncio

617 import os

618 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

619 

620 

621 async def main():

622 # Connection string from environment variable

623 connection_string = os.environ["DATABASE_URL"]

624 

625 options = ClaudeAgentOptions(

626 mcp_servers={

627 "postgres": {

628 "command": "npx",

629 # Pass connection string as argument to the server

630 "args": [

631 "-y",

632 "@modelcontextprotocol/server-postgres",

633 connection_string,

634 ],

635 }

636 },

637 # Allow only read queries, not writes

638 allowed_tools=["mcp__postgres__query"],

639 )

640 

641 # Natural language query - Claude writes the SQL

642 async for message in query(

643 prompt="How many users signed up last week? Break it down by day.",

644 options=options,

645 ):

646 if isinstance(message, ResultMessage) and message.subtype == "success":

647 print(message.result)

648 

649 

650 asyncio.run(main())

651 ```

652</CodeGroup>

653 

654## Error handling

655 

656MCP servers can fail to connect for various reasons: the server process might not be installed, credentials might be invalid, or a remote server might be unreachable.

657 

658The SDK emits a `system` message with subtype `init` at the start of each query. This message includes the connection status for each MCP server. Check the `status` field to detect connection failures before the agent starts working:

659 

660<CodeGroup>

661 ```typescript TypeScript theme={null}

662 import { query } from "@anthropic-ai/claude-agent-sdk";

663 

664 for await (const message of query({

665 prompt: "Process data",

666 options: {

667 mcpServers: {

668 "data-processor": dataServer

669 }

670 }

671 })) {

672 if (message.type === "system" && message.subtype === "init") {

673 const failedServers = message.mcp_servers.filter((s) => s.status !== "connected");

674 

675 if (failedServers.length > 0) {

676 console.warn("Failed to connect:", failedServers);

677 }

678 }

679 

680 if (message.type === "result" && message.subtype === "error_during_execution") {

681 console.error("Execution failed");

682 }

683 }

684 ```

685 

686 ```python Python theme={null}

687 import asyncio

688 from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage, ResultMessage

689 

690 

691 async def main():

692 options = ClaudeAgentOptions(mcp_servers={"data-processor": data_server})

693 

694 async for message in query(prompt="Process data", options=options):

695 if isinstance(message, SystemMessage) and message.subtype == "init":

696 failed_servers = [

697 s

698 for s in message.data.get("mcp_servers", [])

699 if s.get("status") != "connected"

700 ]

701 

702 if failed_servers:

703 print(f"Failed to connect: {failed_servers}")

704 

705 if (

706 isinstance(message, ResultMessage)

707 and message.subtype == "error_during_execution"

708 ):

709 print("Execution failed")

710 

711 

712 asyncio.run(main())

713 ```

714</CodeGroup>

715 

716## Troubleshooting

717 

718### Server shows "failed" status

719 

720Check the `init` message to see which servers failed to connect:

721 

722```typescript theme={null}

723if (message.type === "system" && message.subtype === "init") {

724 for (const server of message.mcp_servers) {

725 if (server.status === "failed") {

726 console.error(`Server ${server.name} failed to connect`);

727 }

728 }

729}

730```

731 

732Common causes:

733 

734* **Missing environment variables**: Ensure required tokens and credentials are set. For stdio servers, check the `env` field matches what the server expects.

735* **Server not installed**: For `npx` commands, verify the package exists and Node.js is in your PATH.

736* **Invalid connection string**: For database servers, verify the connection string format and that the database is accessible.

737* **Network issues**: For remote HTTP/SSE servers, check the URL is reachable and any firewalls allow the connection.

738 

739### Tools not being called

740 

741If Claude sees tools but doesn't use them, check that you've granted permission with `allowedTools`:

742 

743```typescript hidelines={1,-1} theme={null}

744const _ = {

745 options: {

746 mcpServers: {

747 // your servers

748 },

749 allowedTools: ["mcp__servername__*"] // Required for Claude to use the tools

750 }

751};

752```

753 

754### Connection timeouts

755 

756The MCP SDK has a default timeout of 60 seconds for server connections. If your server takes longer to start, the connection will fail. For servers that need more startup time, consider:

757 

758* Using a lighter-weight server if available

759* Pre-warming the server before starting your agent

760* Checking server logs for slow initialization causes

761 

762## Related resources

763 

764* **[Custom tools guide](/en/agent-sdk/custom-tools)**: Build your own MCP server that runs in-process with your SDK application

765* **[Permissions](/en/agent-sdk/permissions)**: Control which MCP tools your agent can use with `allowedTools` and `disallowedTools`

766* **[TypeScript SDK reference](/en/agent-sdk/typescript)**: Full API reference including MCP configuration options

767* **[Python SDK reference](/en/agent-sdk/python)**: Full API reference including MCP configuration options

768* **[MCP server directory](https://github.com/modelcontextprotocol/servers)**: Browse available MCP servers for databases, APIs, and more

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# Migrate to Claude Agent SDK

6 

7> Guide for migrating the Claude Code TypeScript and Python SDKs to the Claude Agent SDK

8 

9## Overview

10 

11The Claude Code SDK has been renamed to the **Claude Agent SDK** and its documentation has been reorganized. This change reflects the SDK's broader capabilities for building AI agents beyond just coding tasks.

12 

13## What's Changed

14 

15| Aspect | Old | New |

16| :------------------------- | :-------------------------- | :------------------------------- |

17| **Package Name (TS/JS)** | `@anthropic-ai/claude-code` | `@anthropic-ai/claude-agent-sdk` |

18| **Python Package** | `claude-code-sdk` | `claude-agent-sdk` |

19| **Documentation Location** | Claude Code docs | API Guide → Agent SDK section |

20 

21<Note>

22 **Documentation Changes:** The Agent SDK documentation has moved from the Claude Code docs to the API Guide under a dedicated [Agent SDK](/en/agent-sdk/overview) section. The Claude Code docs now focus on the CLI tool and automation features.

23</Note>

24 

25## Migration Steps

26 

27### For TypeScript/JavaScript Projects

28 

29**1. Uninstall the old package:**

30 

31```bash theme={null}

32npm uninstall @anthropic-ai/claude-code

33```

34 

35**2. Install the new package:**

36 

37```bash theme={null}

38npm install @anthropic-ai/claude-agent-sdk

39```

40 

41**3. Update your imports:**

42 

43Change all imports from `@anthropic-ai/claude-code` to `@anthropic-ai/claude-agent-sdk`:

44 

45```typescript theme={null}

46// Before

47import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-code";

48 

49// After

50import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";

51```

52 

53**4. Update package.json dependencies:**

54 

55If you have the package listed in your `package.json`, update it:

56 

57Before:

58 

59```json theme={null}

60{

61 "dependencies": {

62 "@anthropic-ai/claude-code": "^0.0.42"

63 }

64}

65```

66 

67After:

68 

69```json theme={null}

70{

71 "dependencies": {

72 "@anthropic-ai/claude-agent-sdk": "^0.2.0"

73 }

74}

75```

76 

77That's it! No other code changes are required.

78 

79### For Python Projects

80 

81**1. Uninstall the old package:**

82 

83```bash theme={null}

84pip uninstall claude-code-sdk

85```

86 

87**2. Install the new package:**

88 

89```bash theme={null}

90pip install claude-agent-sdk

91```

92 

93**3. Update your imports:**

94 

95Change all imports from `claude_code_sdk` to `claude_agent_sdk`:

96 

97```python theme={null}

98# Before

99from claude_code_sdk import query, ClaudeCodeOptions

100 

101# After

102from claude_agent_sdk import query, ClaudeAgentOptions

103```

104 

105**4. Update type names:**

106 

107Change `ClaudeCodeOptions` to `ClaudeAgentOptions`:

108 

109```python theme={null}

110# Before

111from claude_code_sdk import query, ClaudeCodeOptions

112 

113options = ClaudeCodeOptions(model="claude-opus-4-7")

114 

115# After

116from claude_agent_sdk import query, ClaudeAgentOptions

117 

118options = ClaudeAgentOptions(model="claude-opus-4-7")

119```

120 

121**5. Review [breaking changes](#breaking-changes)**

122 

123Make any code changes needed to complete the migration.

124 

125## Breaking changes

126 

127<Warning>

128 To improve isolation and explicit configuration, Claude Agent SDK v0.1.0 introduces breaking changes for users migrating from Claude Code SDK. Review this section carefully before migrating.

129</Warning>

130 

131### Python: ClaudeCodeOptions renamed to ClaudeAgentOptions

132 

133**What changed:** The Python SDK type `ClaudeCodeOptions` has been renamed to `ClaudeAgentOptions`.

134 

135**Migration:**

136 

137```python theme={null}

138# BEFORE (claude-code-sdk)

139from claude_code_sdk import query, ClaudeCodeOptions

140 

141options = ClaudeCodeOptions(model="claude-opus-4-7", permission_mode="acceptEdits")

142 

143# AFTER (claude-agent-sdk)

144from claude_agent_sdk import query, ClaudeAgentOptions

145 

146options = ClaudeAgentOptions(model="claude-opus-4-7", permission_mode="acceptEdits")

147```

148 

149**Why this changed:** The type name now matches the "Claude Agent SDK" branding and provides consistency across the SDK's naming conventions.

150 

151### System prompt no longer default

152 

153**What changed:** The SDK no longer uses Claude Code's system prompt by default.

154 

155**Migration:**

156 

157<CodeGroup>

158 ```typescript TypeScript theme={null}

159 // BEFORE (v0.0.x) - Used Claude Code's system prompt by default

160 const result = query({ prompt: "Hello" });

161 

162 // AFTER (v0.1.0) - Uses minimal system prompt by default

163 // To get the old behavior, explicitly request Claude Code's preset:

164 const result = query({

165 prompt: "Hello",

166 options: {

167 systemPrompt: { type: "preset", preset: "claude_code" }

168 }

169 });

170 

171 // Or use a custom system prompt:

172 const result = query({

173 prompt: "Hello",

174 options: {

175 systemPrompt: "You are a helpful coding assistant"

176 }

177 });

178 ```

179 

180 ```python Python theme={null}

181 # BEFORE (v0.0.x) - Used Claude Code's system prompt by default

182 async for message in query(prompt="Hello"):

183 print(message)

184 

185 # AFTER (v0.1.0) - Uses minimal system prompt by default

186 # To get the old behavior, explicitly request Claude Code's preset:

187 from claude_agent_sdk import query, ClaudeAgentOptions

188 

189 async for message in query(

190 prompt="Hello",

191 options=ClaudeAgentOptions(

192 system_prompt={"type": "preset", "preset": "claude_code"} # Use the preset

193 ),

194 ):

195 print(message)

196 

197 # Or use a custom system prompt:

198 async for message in query(

199 prompt="Hello",

200 options=ClaudeAgentOptions(system_prompt="You are a helpful coding assistant"),

201 ):

202 print(message)

203 ```

204</CodeGroup>

205 

206**Why this changed:** Provides better control and isolation for SDK applications. You can now build agents with custom behavior without inheriting Claude Code's CLI-focused instructions.

207 

208### Settings Sources No Longer Loaded by Default

209 

210**What changed:** The SDK no longer reads from filesystem settings (CLAUDE.md, settings.json, slash commands, etc.) by default.

211 

212**Migration:**

213 

214<CodeGroup>

215 ```typescript TypeScript theme={null}

216 // BEFORE (v0.0.x) - Loaded all settings automatically

217 const result = query({ prompt: "Hello" });

218 // Would read from:

219 // - ~/.claude/settings.json (user)

220 // - .claude/settings.json (project)

221 // - .claude/settings.local.json (local)

222 // - CLAUDE.md files

223 // - Custom slash commands

224 

225 // AFTER (v0.1.0) - No settings loaded by default

226 // To get the old behavior:

227 const result = query({

228 prompt: "Hello",

229 options: {

230 settingSources: ["user", "project", "local"]

231 }

232 });

233 

234 // Or load only specific sources:

235 const result = query({

236 prompt: "Hello",

237 options: {

238 settingSources: ["project"] // Only project settings

239 }

240 });

241 ```

242 

243 ```python Python theme={null}

244 # BEFORE (v0.0.x) - Loaded all settings automatically

245 async for message in query(prompt="Hello"):

246 print(message)

247 # Would read from:

248 # - ~/.claude/settings.json (user)

249 # - .claude/settings.json (project)

250 # - .claude/settings.local.json (local)

251 # - CLAUDE.md files

252 # - Custom slash commands

253 

254 # AFTER (v0.1.0) - No settings loaded by default

255 # To get the old behavior:

256 from claude_agent_sdk import query, ClaudeAgentOptions

257 

258 async for message in query(

259 prompt="Hello",

260 options=ClaudeAgentOptions(setting_sources=["user", "project", "local"]),

261 ):

262 print(message)

263 

264 # Or load only specific sources:

265 async for message in query(

266 prompt="Hello",

267 options=ClaudeAgentOptions(

268 setting_sources=["project"] # Only project settings

269 ),

270 ):

271 print(message)

272 ```

273</CodeGroup>

274 

275**Why this changed:** Ensures SDK applications have predictable behavior independent of local filesystem configurations. This is especially important for:

276 

277* **CI/CD environments** - Consistent behavior without local customizations

278* **Deployed applications** - No dependency on filesystem settings

279* **Testing** - Isolated test environments

280* **Multi-tenant systems** - Prevent settings leakage between users

281 

282<Warning>

283 Current SDK releases have reverted this default for `query()`: omitting the option once again loads user, project, and local settings, matching the CLI. Pass `settingSources: []` in TypeScript or `setting_sources=[]` in Python if your application depends on the isolated behavior described above. Python SDK 0.1.59 and earlier treated an empty list the same as omitting the option, so upgrade before relying on `setting_sources=[]`. See [What settingSources does not control](/en/agent-sdk/claude-code-features#what-settingsources-does-not-control) for inputs that are read even when `settingSources` is `[]`.

284</Warning>

285 

286## Why the Rename?

287 

288The Claude Code SDK was originally designed for coding tasks, but it has evolved into a powerful framework for building all types of AI agents. The new name "Claude Agent SDK" better reflects its capabilities:

289 

290* Building business agents (legal assistants, finance advisors, customer support)

291* Creating specialized coding agents (SRE bots, security reviewers, code review agents)

292* Developing custom agents for any domain with tool use, MCP integration, and more

293 

294## Getting Help

295 

296If you encounter any issues during migration:

297 

298**For TypeScript/JavaScript:**

299 

3001. Check that all imports are updated to use `@anthropic-ai/claude-agent-sdk`

3012. Verify your package.json has the new package name

3023. Run `npm install` to ensure dependencies are updated

303 

304**For Python:**

305 

3061. Check that all imports are updated to use `claude_agent_sdk`

3072. Verify your requirements.txt or pyproject.toml has the new package name

3083. Run `pip install claude-agent-sdk` to ensure the package is installed

309 

310## Next Steps

311 

312* Explore the [Agent SDK Overview](/en/agent-sdk/overview) to learn about available features

313* Check out the [TypeScript SDK Reference](/en/agent-sdk/typescript) for detailed API documentation

314* Review the [Python SDK Reference](/en/agent-sdk/python) for Python-specific documentation

315* Learn about [Custom Tools](/en/agent-sdk/custom-tools) and [MCP Integration](/en/agent-sdk/mcp)

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# Modifying system prompts

6 

7> Learn how to customize Claude's behavior by modifying system prompts using three approaches - output styles, systemPrompt with append, and custom system prompts.

8 

9System prompts define Claude's behavior, capabilities, and response style. The Claude Agent SDK provides three ways to customize system prompts: using output styles (persistent, file-based configurations), appending to Claude Code's prompt, or using a fully custom prompt.

10 

11## Understanding system prompts

12 

13A system prompt is the initial instruction set that shapes how Claude behaves throughout a conversation.

14 

15<Note>

16 **Default behavior:** The Agent SDK uses a **minimal system prompt** by default. It contains only essential tool instructions but omits Claude Code's coding guidelines, response style, and project context. To include the full Claude Code system prompt, specify `systemPrompt: { type: "preset", preset: "claude_code" }` in TypeScript or `system_prompt={"type": "preset", "preset": "claude_code"}` in Python.

17</Note>

18 

19Claude Code's system prompt includes:

20 

21* Tool usage instructions and available tools

22* Code style and formatting guidelines

23* Response tone and verbosity settings

24* Security and safety instructions

25* Context about the current working directory and environment

26 

27## Methods of modification

28 

29### Method 1: CLAUDE.md files (project-level instructions)

30 

31CLAUDE.md files provide project-specific context and instructions that are automatically read by the Agent SDK when it runs in a directory. They serve as persistent "memory" for your project.

32 

33#### How CLAUDE.md works with the SDK

34 

35**Location and discovery:**

36 

37* **Project-level:** `CLAUDE.md` or `.claude/CLAUDE.md` in your working directory

38* **User-level:** `~/.claude/CLAUDE.md` for global instructions across all projects

39 

40CLAUDE.md files are read when the corresponding setting source is enabled: `'project'` for project-level CLAUDE.md and `'user'` for `~/.claude/CLAUDE.md`. With default `query()` options both sources are enabled, so CLAUDE.md loads automatically. If you set `settingSources` (TypeScript) or `setting_sources` (Python) explicitly, include the sources you need. CLAUDE.md loading is controlled by setting sources, not by the `claude_code` preset.

41 

42**Content format:**

43CLAUDE.md files use plain markdown and can contain:

44 

45* Coding guidelines and standards

46* Project-specific context

47* Common commands or workflows

48* API conventions

49* Testing requirements

50 

51#### Example CLAUDE.md

52 

53```markdown theme={null}

54# Project Guidelines

55 

56## Code Style

57 

58- Use TypeScript strict mode

59- Prefer functional components in React

60- Always include JSDoc comments for public APIs

61 

62## Testing

63 

64- Run `npm test` before committing

65- Maintain >80% code coverage

66- Use jest for unit tests, playwright for E2E

67 

68## Commands

69 

70- Build: `npm run build`

71- Dev server: `npm run dev`

72- Type check: `npm run typecheck`

73```

74 

75#### Using CLAUDE.md with the SDK

76 

77<CodeGroup>

78 ```typescript TypeScript theme={null}

79 import { query } from "@anthropic-ai/claude-agent-sdk";

80 

81 const messages = [];

82 

83 for await (const message of query({

84 prompt: "Add a new React component for user profiles",

85 options: {

86 systemPrompt: {

87 type: "preset",

88 preset: "claude_code" // Use Claude Code's system prompt

89 },

90 settingSources: ["project"] // Loads CLAUDE.md from project

91 }

92 })) {

93 messages.push(message);

94 }

95 

96 // Now Claude has access to your project guidelines from CLAUDE.md

97 ```

98 

99 ```python Python theme={null}

100 from claude_agent_sdk import query, ClaudeAgentOptions

101 

102 messages = []

103 

104 async for message in query(

105 prompt="Add a new React component for user profiles",

106 options=ClaudeAgentOptions(

107 system_prompt={

108 "type": "preset",

109 "preset": "claude_code", # Use Claude Code's system prompt

110 },

111 setting_sources=["project"], # Loads CLAUDE.md from project

112 ),

113 ):

114 messages.append(message)

115 

116 # Now Claude has access to your project guidelines from CLAUDE.md

117 ```

118</CodeGroup>

119 

120#### When to use CLAUDE.md

121 

122**Best for:**

123 

124* **Team-shared context** - Guidelines everyone should follow

125* **Project conventions** - Coding standards, file structure, naming patterns

126* **Common commands** - Build, test, deploy commands specific to your project

127* **Long-term memory** - Context that should persist across all sessions

128* **Version-controlled instructions** - Commit to git so the team stays in sync

129 

130**Key characteristics:**

131 

132* ✅ Persistent across all sessions in a project

133* ✅ Shared with team via git

134* ✅ Automatic discovery (no code changes needed)

135* ⚠️ Not loaded if you pass `settingSources: []`

136 

137### Method 2: Output styles (persistent configurations)

138 

139Output styles are saved configurations that modify Claude's system prompt. They're stored as markdown files and can be reused across sessions and projects.

140 

141#### Creating an output style

142 

143<CodeGroup>

144 ```typescript TypeScript theme={null}

145 import { writeFile, mkdir } from "fs/promises";

146 import { join } from "path";

147 import { homedir } from "os";

148 

149 async function createOutputStyle(name: string, description: string, prompt: string) {

150 // User-level: ~/.claude/output-styles

151 // Project-level: .claude/output-styles

152 const outputStylesDir = join(homedir(), ".claude", "output-styles");

153 

154 await mkdir(outputStylesDir, { recursive: true });

155 

156 const content = `---

157 name: ${name}

158 description: ${description}

159 ---

160 

161 ${prompt}`;

162 

163 const filePath = join(outputStylesDir, `${name.toLowerCase().replace(/\s+/g, "-")}.md`);

164 await writeFile(filePath, content, "utf-8");

165 }

166 

167 // Example: Create a code review specialist

168 await createOutputStyle(

169 "Code Reviewer",

170 "Thorough code review assistant",

171 `You are an expert code reviewer.

172 

173 For every code submission:

174 1. Check for bugs and security issues

175 2. Evaluate performance

176 3. Suggest improvements

177 4. Rate code quality (1-10)`

178 );

179 ```

180 

181 ```python Python theme={null}

182 from pathlib import Path

183 

184 

185 async def create_output_style(name: str, description: str, prompt: str):

186 # User-level: ~/.claude/output-styles

187 # Project-level: .claude/output-styles

188 output_styles_dir = Path.home() / ".claude" / "output-styles"

189 

190 output_styles_dir.mkdir(parents=True, exist_ok=True)

191 

192 content = f"""---

193 name: {name}

194 description: {description}

195 ---

196 

197 {prompt}"""

198 

199 file_name = name.lower().replace(" ", "-") + ".md"

200 file_path = output_styles_dir / file_name

201 file_path.write_text(content, encoding="utf-8")

202 

203 

204 # Example: Create a code review specialist

205 await create_output_style(

206 "Code Reviewer",

207 "Thorough code review assistant",

208 """You are an expert code reviewer.

209 

210 For every code submission:

211 1. Check for bugs and security issues

212 2. Evaluate performance

213 3. Suggest improvements

214 4. Rate code quality (1-10)""",

215 )

216 ```

217</CodeGroup>

218 

219#### Using output styles

220 

221Once created, activate output styles via:

222 

223* **CLI**: `/output-style [style-name]`

224* **Settings**: `.claude/settings.local.json`

225* **Create new**: `/output-style:new [description]`

226 

227**Note for SDK users:** Output styles are loaded when you include `settingSources: ['user']` or `settingSources: ['project']` (TypeScript) / `setting_sources=["user"]` or `setting_sources=["project"]` (Python) in your options.

228 

229### Method 3: Using `systemPrompt` with append

230 

231You can use the Claude Code preset with an `append` property to add your custom instructions while preserving all built-in functionality.

232 

233<CodeGroup>

234 ```typescript TypeScript theme={null}

235 import { query } from "@anthropic-ai/claude-agent-sdk";

236 

237 const messages = [];

238 

239 for await (const message of query({

240 prompt: "Help me write a Python function to calculate fibonacci numbers",

241 options: {

242 systemPrompt: {

243 type: "preset",

244 preset: "claude_code",

245 append: "Always include detailed docstrings and type hints in Python code."

246 }

247 }

248 })) {

249 messages.push(message);

250 if (message.type === "assistant") {

251 console.log(message.message.content);

252 }

253 }

254 ```

255 

256 ```python Python theme={null}

257 from claude_agent_sdk import query, ClaudeAgentOptions

258 

259 messages = []

260 

261 async for message in query(

262 prompt="Help me write a Python function to calculate fibonacci numbers",

263 options=ClaudeAgentOptions(

264 system_prompt={

265 "type": "preset",

266 "preset": "claude_code",

267 "append": "Always include detailed docstrings and type hints in Python code.",

268 }

269 ),

270 ):

271 messages.append(message)

272 if message.type == "assistant":

273 print(message.message.content)

274 ```

275</CodeGroup>

276 

277#### Improve prompt caching across users and machines

278 

279By default, two sessions that use the same `claude_code` preset and `append` text still cannot share a prompt cache entry if they run from different working directories. This is because the preset embeds per-session context in the system prompt ahead of your `append` text: the working directory, platform and OS version, current date, git status, and auto-memory paths. Any difference in that context produces a different system prompt and a cache miss.

280 

281To make the system prompt identical across sessions, set `excludeDynamicSections: true` in TypeScript or `"exclude_dynamic_sections": True` in Python. The per-session context moves into the first user message, leaving only the static preset and your `append` text in the system prompt so identical configurations share a cache entry across users and machines.

282 

283<Note>

284 `excludeDynamicSections` requires `@anthropic-ai/claude-agent-sdk` v0.2.98 or later, or `claude-agent-sdk` v0.1.58 or later for Python. It applies only to the preset object form and has no effect when `systemPrompt` is a string.

285</Note>

286 

287The following example pairs a shared `append` block with `excludeDynamicSections` so a fleet of agents running from different directories can reuse the same cached system prompt:

288 

289<CodeGroup>

290 ```typescript TypeScript theme={null}

291 import { query } from "@anthropic-ai/claude-agent-sdk";

292 

293 for await (const message of query({

294 prompt: "Triage the open issues in this repo",

295 options: {

296 systemPrompt: {

297 type: "preset",

298 preset: "claude_code",

299 append: "You operate Acme's internal triage workflow. Label issues by component and severity.",

300 excludeDynamicSections: true

301 }

302 }

303 })) {

304 // ...

305 }

306 ```

307 

308 ```python Python theme={null}

309 from claude_agent_sdk import query, ClaudeAgentOptions

310 

311 async for message in query(

312 prompt="Triage the open issues in this repo",

313 options=ClaudeAgentOptions(

314 system_prompt={

315 "type": "preset",

316 "preset": "claude_code",

317 "append": "You operate Acme's internal triage workflow. Label issues by component and severity.",

318 "exclude_dynamic_sections": True,

319 },

320 ),

321 ):

322 ...

323 ```

324</CodeGroup>

325 

326**Tradeoffs:** the working directory, git status, and memory location still reach Claude, but as part of the first user message rather than the system prompt. Instructions in the user message carry marginally less weight than the same text in the system prompt, so Claude may rely on them less strongly when reasoning about the current directory or auto-memory paths. Enable this option when cross-session cache reuse matters more than maximally authoritative environment context.

327 

328For the equivalent flag in non-interactive CLI mode, see [`--exclude-dynamic-system-prompt-sections`](/en/cli-reference).

329 

330### Method 4: Custom system prompts

331 

332You can provide a custom string as `systemPrompt` to replace the default entirely with your own instructions.

333 

334<CodeGroup>

335 ```typescript TypeScript theme={null}

336 import { query } from "@anthropic-ai/claude-agent-sdk";

337 

338 const customPrompt = `You are a Python coding specialist.

339 Follow these guidelines:

340 - Write clean, well-documented code

341 - Use type hints for all functions

342 - Include comprehensive docstrings

343 - Prefer functional programming patterns when appropriate

344 - Always explain your code choices`;

345 

346 const messages = [];

347 

348 for await (const message of query({

349 prompt: "Create a data processing pipeline",

350 options: {

351 systemPrompt: customPrompt

352 }

353 })) {

354 messages.push(message);

355 if (message.type === "assistant") {

356 console.log(message.message.content);

357 }

358 }

359 ```

360 

361 ```python Python theme={null}

362 from claude_agent_sdk import query, ClaudeAgentOptions

363 

364 custom_prompt = """You are a Python coding specialist.

365 Follow these guidelines:

366 - Write clean, well-documented code

367 - Use type hints for all functions

368 - Include comprehensive docstrings

369 - Prefer functional programming patterns when appropriate

370 - Always explain your code choices"""

371 

372 messages = []

373 

374 async for message in query(

375 prompt="Create a data processing pipeline",

376 options=ClaudeAgentOptions(system_prompt=custom_prompt),

377 ):

378 messages.append(message)

379 if message.type == "assistant":

380 print(message.message.content)

381 ```

382</CodeGroup>

383 

384## Comparison of all four approaches

385 

386| Feature | CLAUDE.md | Output Styles | `systemPrompt` with append | Custom `systemPrompt` |

387| ----------------------- | ---------------- | --------------- | -------------------------- | ---------------------- |

388| **Persistence** | Per-project file | Saved as files | Session only | Session only |

389| **Reusability** | Per-project | Across projects | Code duplication | Code duplication |

390| **Management** | On filesystem | CLI + files | In code | In code |

391| **Default tools** | Preserved | Preserved | Preserved | Lost (unless included) |

392| **Built-in safety** | Maintained | Maintained | Maintained | Must be added |

393| **Environment context** | Automatic | Automatic | Automatic | Must be provided |

394| **Customization level** | Additions only | Replace default | Additions only | Complete control |

395| **Version control** | With project | Yes | With code | With code |

396| **Scope** | Project-specific | User or project | Code session | Code session |

397 

398**Note:** "With append" means using `systemPrompt: { type: "preset", preset: "claude_code", append: "..." }` in TypeScript or `system_prompt={"type": "preset", "preset": "claude_code", "append": "..."}` in Python.

399 

400## Use cases and best practices

401 

402### When to use CLAUDE.md

403 

404**Best for:**

405 

406* Project-specific coding standards and conventions

407* Documenting project structure and architecture

408* Listing common commands (build, test, deploy)

409* Team-shared context that should be version controlled

410* Instructions that apply to all SDK usage in a project

411 

412**Examples:**

413 

414* "All API endpoints should use async/await patterns"

415* "Run `npm run lint:fix` before committing"

416* "Database migrations are in the `migrations/` directory"

417 

418CLAUDE.md files load when the `project` setting source is enabled, which it is for default `query()` options. If you set `settingSources` (TypeScript) or `setting_sources` (Python) explicitly, include `'project'` to keep loading project-level CLAUDE.md.

419 

420### When to use output styles

421 

422**Best for:**

423 

424* Persistent behavior changes across sessions

425* Team-shared configurations

426* Specialized assistants (code reviewer, data scientist, DevOps)

427* Complex prompt modifications that need versioning

428 

429**Examples:**

430 

431* Creating a dedicated SQL optimization assistant

432* Building a security-focused code reviewer

433* Developing a teaching assistant with specific pedagogy

434 

435### When to use `systemPrompt` with append

436 

437**Best for:**

438 

439* Adding specific coding standards or preferences

440* Customizing output formatting

441* Adding domain-specific knowledge

442* Modifying response verbosity

443* Enhancing Claude Code's default behavior without losing tool instructions

444 

445### When to use custom `systemPrompt`

446 

447**Best for:**

448 

449* Complete control over Claude's behavior

450* Specialized single-session tasks

451* Testing new prompt strategies

452* Situations where default tools aren't needed

453* Building specialized agents with unique behavior

454 

455## Combining approaches

456 

457You can combine these methods for maximum flexibility:

458 

459### Example: Output style with session-specific additions

460 

461<CodeGroup>

462 ```typescript TypeScript theme={null}

463 import { query } from "@anthropic-ai/claude-agent-sdk";

464 

465 // Assuming "Code Reviewer" output style is active (via /output-style)

466 // Add session-specific focus areas

467 const messages = [];

468 

469 for await (const message of query({

470 prompt: "Review this authentication module",

471 options: {

472 systemPrompt: {

473 type: "preset",

474 preset: "claude_code",

475 append: `

476 For this review, prioritize:

477 - OAuth 2.0 compliance

478 - Token storage security

479 - Session management

480 `

481 }

482 }

483 })) {

484 messages.push(message);

485 }

486 ```

487 

488 ```python Python theme={null}

489 from claude_agent_sdk import query, ClaudeAgentOptions

490 

491 # Assuming "Code Reviewer" output style is active (via /output-style)

492 # Add session-specific focus areas

493 messages = []

494 

495 async for message in query(

496 prompt="Review this authentication module",

497 options=ClaudeAgentOptions(

498 system_prompt={

499 "type": "preset",

500 "preset": "claude_code",

501 "append": """

502 For this review, prioritize:

503 - OAuth 2.0 compliance

504 - Token storage security

505 - Session management

506 """,

507 }

508 ),

509 ):

510 messages.append(message)

511 ```

512</CodeGroup>

513 

514## See also

515 

516* [Output styles](/en/output-styles) - Complete output styles documentation

517* [TypeScript SDK guide](/en/agent-sdk/typescript) - Complete SDK usage guide

518* [Configuration guide](/en/settings) - General configuration options

agent-sdk/observability.md +216 −0 added

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# Observability with OpenTelemetry

6 

7> Export traces, metrics, and events from the Agent SDK to your observability backend using OpenTelemetry.

8 

9When you run agents in production, you need visibility into what they did:

10 

11* which tools they called

12* how long each model request took

13* how many tokens were spent

14* where failures occurred

15 

16The Agent SDK can export this data as OpenTelemetry traces, metrics, and log events to any backend that accepts the OpenTelemetry Protocol (OTLP), such as Honeycomb, Datadog, Grafana, Langfuse, or a self-hosted collector.

17 

18This guide explains how the SDK emits telemetry, how to configure the export, and how to tag and filter the data once it reaches your backend. To read token usage and cost directly from the SDK response stream instead of exporting to a backend, see [Track cost and usage](/en/agent-sdk/cost-tracking).

19 

20## How telemetry flows from the SDK

21 

22The Agent SDK runs the Claude Code CLI as a child process and communicates with it over a local pipe. The CLI has OpenTelemetry instrumentation built in: it records spans around each model request and tool execution, emits metrics for token and cost counters, and emits structured log events for prompts and tool results. The SDK does not produce telemetry of its own. Instead, it passes configuration through to the CLI process, and the CLI exports directly to your collector.

23 

24Configuration is passed as environment variables. By default, the child process inherits your application's environment, so you can configure telemetry in either of two places:

25 

26* **Process environment:** set the variables in your shell, container, or orchestrator before your application starts. Every `query()` call picks them up automatically with no code change. This is the recommended approach for production deployments.

27* **Per-call options:** set the variables in `ClaudeAgentOptions.env` (Python) or `options.env` (TypeScript). Use this when different agents in the same process need different telemetry settings. In Python, `env` is merged on top of the inherited environment. In TypeScript, `env` replaces the inherited environment entirely, so include `...process.env` in the object you pass.

28 

29The CLI exports three independent OpenTelemetry signals. Each has its own enable switch and its own exporter, so you can turn on only the ones you need.

30 

31| Signal | What it contains | Enable with |

32| ---------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------- |

33| Metrics | Counters for tokens, cost, sessions, lines of code, and tool decisions | `OTEL_METRICS_EXPORTER` |

34| Log events | Structured records for each prompt, API request, API error, and tool result | `OTEL_LOGS_EXPORTER` |

35| Traces | Spans for each interaction, model request, tool call, and hook (beta) | `OTEL_TRACES_EXPORTER` plus `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1` |

36 

37For the complete list of metric names, event names, and attributes, see the Claude Code [Monitoring](/en/monitoring-usage) reference. The Agent SDK emits the same data because it runs the same CLI. Span names are listed in [Read agent traces](#read-agent-traces) below.

38 

39## Enable telemetry export

40 

41Telemetry is off until you set `CLAUDE_CODE_ENABLE_TELEMETRY=1` and choose at least one exporter. The most common configuration sends all three signals over OTLP HTTP to a collector.

42 

43The following example sets the variables in a dictionary and passes them through `options.env`. The agent runs a single task, and the CLI exports spans, metrics, and events to the collector at `collector.example.com` while the loop consumes the response stream:

44 

45<CodeGroup>

46 ```python Python theme={null}

47 import asyncio

48 from claude_agent_sdk import query, ClaudeAgentOptions

49 

50 OTEL_ENV = {

51 "CLAUDE_CODE_ENABLE_TELEMETRY": "1",

52 # Required for traces, which are in beta. Metrics and log events do not need this.

53 "CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",

54 # Choose an exporter per signal. Use otlp for the SDK; see the Note below.

55 "OTEL_TRACES_EXPORTER": "otlp",

56 "OTEL_METRICS_EXPORTER": "otlp",

57 "OTEL_LOGS_EXPORTER": "otlp",

58 # Standard OTLP transport configuration.

59 "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",

60 "OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4318",

61 "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer your-token",

62 }

63 

64 

65 async def main():

66 options = ClaudeAgentOptions(env=OTEL_ENV)

67 async for message in query(

68 prompt="List the files in this directory", options=options

69 ):

70 print(message)

71 

72 

73 asyncio.run(main())

74 ```

75 

76 ```typescript TypeScript theme={null}

77 import { query } from "@anthropic-ai/claude-agent-sdk";

78 

79 const otelEnv = {

80 CLAUDE_CODE_ENABLE_TELEMETRY: "1",

81 // Required for traces, which are in beta. Metrics and log events do not need this.

82 CLAUDE_CODE_ENHANCED_TELEMETRY_BETA: "1",

83 // Choose an exporter per signal. Use otlp for the SDK; see the Note below.

84 OTEL_TRACES_EXPORTER: "otlp",

85 OTEL_METRICS_EXPORTER: "otlp",

86 OTEL_LOGS_EXPORTER: "otlp",

87 // Standard OTLP transport configuration.

88 OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf",

89 OTEL_EXPORTER_OTLP_ENDPOINT: "http://collector.example.com:4318",

90 OTEL_EXPORTER_OTLP_HEADERS: "Authorization=Bearer your-token",

91 };

92 

93 for await (const message of query({

94 prompt: "List the files in this directory",

95 // env replaces the inherited environment in TypeScript, so spread

96 // process.env first to keep PATH, ANTHROPIC_API_KEY, and other variables.

97 options: { env: { ...process.env, ...otelEnv } },

98 })) {

99 console.log(message);

100 }

101 ```

102</CodeGroup>

103 

104Because the child process inherits your application's environment by default, you can achieve the same result by exporting these variables in a Dockerfile, Kubernetes manifest, or shell profile and omitting `options.env` entirely.

105 

106<Note>

107 The `console` exporter writes telemetry to standard output, which the SDK uses

108 as its message channel. Do not set `console` as an exporter value when running

109 through the SDK. To inspect telemetry locally, point

110 `OTEL_EXPORTER_OTLP_ENDPOINT` at a local collector or an all-in-one Jaeger

111 container instead.

112</Note>

113 

114### Flush telemetry from short-lived calls

115 

116The CLI batches telemetry and exports on an interval. On a clean process exit it attempts to flush pending data, but the flush is bounded by a short timeout, so spans can still be dropped if the collector is slow to respond. If your process is killed before the CLI shuts down, anything still in the batch buffer is lost. Lowering the export intervals reduces both windows.

117 

118By default, metrics export every 60 seconds and traces and logs export every 5 seconds. The following example shortens all three intervals so that data reaches the collector while a short task is still running:

119 

120<CodeGroup>

121 ```python Python theme={null}

122 OTEL_ENV = {

123 # ... exporter configuration from the previous example ...

124 "OTEL_METRIC_EXPORT_INTERVAL": "1000",

125 "OTEL_LOGS_EXPORT_INTERVAL": "1000",

126 "OTEL_TRACES_EXPORT_INTERVAL": "1000",

127 }

128 ```

129 

130 ```typescript TypeScript theme={null}

131 const otelEnv = {

132 // ... exporter configuration from the previous example ...

133 OTEL_METRIC_EXPORT_INTERVAL: "1000",

134 OTEL_LOGS_EXPORT_INTERVAL: "1000",

135 OTEL_TRACES_EXPORT_INTERVAL: "1000",

136 };

137 ```

138</CodeGroup>

139 

140## Read agent traces

141 

142Traces give you the most detailed view of an agent run. With `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1` set, each step of the agent loop becomes a span you can inspect in your tracing backend:

143 

144* **`claude_code.interaction`:** wraps a single turn of the agent loop, from receiving a prompt to producing a response.

145* **`claude_code.llm_request`:** wraps each call to the Claude API, with model name, latency, and token counts as attributes.

146* **`claude_code.tool`:** wraps each tool invocation, with child spans for the permission wait (`claude_code.tool.blocked_on_user`) and the execution itself (`claude_code.tool.execution`).

147* **`claude_code.hook`:** wraps each [hook](/en/agent-sdk/hooks) execution. Requires detailed beta tracing (`ENABLE_BETA_TRACING_DETAILED=1` and `BETA_TRACING_ENDPOINT`) in addition to the variables above.

148 

149The `llm_request`, `tool`, and `hook` spans are children of the enclosing `claude_code.interaction` span. When the agent spawns a subagent through the Task tool, the subagent's `llm_request` and `tool` spans nest under the parent agent's `claude_code.tool` span, so the full delegation chain appears as one trace.

150 

151Spans carry a `session.id` attribute by default. When you make several `query()` calls against the same [session](/en/agent-sdk/sessions), filter on `session.id` in your backend to see them as one timeline. The attribute is omitted if `OTEL_METRICS_INCLUDE_SESSION_ID` is set to a falsy value.

152 

153<Note>

154 Tracing is in beta. Span names and attributes may change between releases. See

155 [Traces (beta)](/en/monitoring-usage#traces-beta) in the Monitoring reference

156 for the trace exporter configuration variables.

157</Note>

158 

159## Link traces to your application

160 

161The SDK automatically propagates W3C trace context into the CLI subprocess. When you call `query()` while an OpenTelemetry span is active in your application, the SDK injects `TRACEPARENT` and `TRACESTATE` into the child process environment, and the CLI reads them so its `claude_code.interaction` span becomes a child of your span. The agent run then appears inside your application's trace instead of as a disconnected root.

162 

163The CLI also forwards `TRACEPARENT` to every Bash and PowerShell command it runs. If a command launched through the Bash tool emits its own OpenTelemetry spans, those spans nest under the `claude_code.tool.execution` span that wraps the command.

164 

165Auto-injection is skipped when you set `TRACEPARENT` explicitly in `options.env`, so you can pin a specific parent context if needed. Interactive CLI sessions ignore inbound `TRACEPARENT` entirely; only Agent SDK and `claude -p` runs honor it. See [Traces (beta)](/en/monitoring-usage#traces-beta) in the Monitoring reference for the full span and attribute reference.

166 

167## Tag telemetry from your agent

168 

169By default, the CLI reports `service.name` as `claude-code`. If you run several agents, or run the SDK alongside other services that export to the same collector, override the service name and add resource attributes so you can filter by agent in your backend.

170 

171The following example renames the service and attaches deployment metadata. These values are applied as OpenTelemetry resource attributes on every span, metric, and event the agent emits:

172 

173<CodeGroup>

174 ```python Python theme={null}

175 options = ClaudeAgentOptions(

176 env={

177 # ... exporter configuration ...

178 "OTEL_SERVICE_NAME": "support-triage-agent",

179 "OTEL_RESOURCE_ATTRIBUTES": "service.version=1.4.0,deployment.environment=production",

180 },

181 )

182 ```

183 

184 ```typescript TypeScript theme={null}

185 const options = {

186 env: {

187 ...process.env,

188 // ... exporter configuration ...

189 OTEL_SERVICE_NAME: "support-triage-agent",

190 OTEL_RESOURCE_ATTRIBUTES:

191 "service.version=1.4.0,deployment.environment=production",

192 },

193 };

194 ```

195</CodeGroup>

196 

197## Control sensitive data in exports

198 

199Telemetry is structural by default. Durations, model names, and tool names are recorded on every span; token counts are recorded when the underlying API request returns usage data, so spans for failed or aborted requests may omit them. The content your agent reads and writes is not recorded by default. These opt-in variables add content to the exported data:

200 

201| Variable | Adds |

202| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

203| `OTEL_LOG_USER_PROMPTS=1` | Prompt text on `claude_code.user_prompt` events and on the `claude_code.interaction` span |

204| `OTEL_LOG_TOOL_DETAILS=1` | Tool input arguments (file paths, shell commands, search patterns) on `claude_code.tool_result` events |

205| `OTEL_LOG_TOOL_CONTENT=1` | Full tool input and output bodies as span events on `claude_code.tool`, truncated at 60 KB. Requires [tracing](#read-agent-traces) to be enabled |

206| `OTEL_LOG_RAW_API_BODIES` | Full Anthropic Messages API request and response JSON as `claude_code.api_request_body` and `claude_code.api_response_body` log events. Set to `1` for inline bodies truncated at 60 KB, or `file:<dir>` for untruncated bodies on disk with a `body_ref` path in the event. Bodies include the entire conversation history and have extended-thinking content redacted. Enabling this implies consent to everything the three variables above would reveal |

207 

208Leave these unset unless your observability pipeline is approved to store the data your agent handles. See [Security and privacy](/en/monitoring-usage#security-and-privacy) in the Monitoring reference for the full list of attributes and redaction behavior.

209 

210## Related documentation

211 

212These guides cover adjacent topics for monitoring and deploying agents:

213 

214* [Track cost and usage](/en/agent-sdk/cost-tracking): read token and cost data from the message stream without an external backend.

215* [Hosting the Agent SDK](/en/agent-sdk/hosting): deploy agents in containers where you can set OpenTelemetry variables at the environment level.

216* [Monitoring](/en/monitoring-usage): the complete reference for every environment variable, metric, and event the CLI emits.

agent-sdk/overview.md +592 −0 added

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# Agent SDK overview

6 

7> Build production AI agents with Claude Code as a library

8 

9<Note>

10 The Claude Code SDK has been renamed to the Claude Agent SDK. If you're migrating from the old SDK, see the [Migration Guide](/en/agent-sdk/migration-guide).

11</Note>

12 

13Build AI agents that autonomously read files, run commands, search the web, edit code, and more. The Agent SDK gives you the same tools, agent loop, and context management that power Claude Code, programmable in Python and TypeScript.

14 

15<Note>

16 Opus 4.7 (`claude-opus-4-7`) requires Agent SDK v0.2.111 or later. If you see a `thinking.type.enabled` API error, see [Troubleshooting](/en/agent-sdk/quickstart#troubleshooting).

17</Note>

18 

19<CodeGroup>

20 ```python Python theme={null}

21 import asyncio

22 from claude_agent_sdk import query, ClaudeAgentOptions

23 

24 

25 async def main():

26 async for message in query(

27 prompt="Find and fix the bug in auth.py",

28 options=ClaudeAgentOptions(allowed_tools=["Read", "Edit", "Bash"]),

29 ):

30 print(message) # Claude reads the file, finds the bug, edits it

31 

32 

33 asyncio.run(main())

34 ```

35 

36 ```typescript TypeScript theme={null}

37 import { query } from "@anthropic-ai/claude-agent-sdk";

38 

39 for await (const message of query({

40 prompt: "Find and fix the bug in auth.ts",

41 options: { allowedTools: ["Read", "Edit", "Bash"] }

42 })) {

43 console.log(message); // Claude reads the file, finds the bug, edits it

44 }

45 ```

46</CodeGroup>

47 

48The Agent SDK includes built-in tools for reading files, running commands, and editing code, so your agent can start working immediately without you implementing tool execution. Dive into the quickstart or explore real agents built with the SDK:

49 

50<CardGroup cols={2}>

51 <Card title="Quickstart" icon="play" href="/en/agent-sdk/quickstart">

52 Build a bug-fixing agent in minutes

53 </Card>

54 

55 <Card title="Example agents" icon="star" href="https://github.com/anthropics/claude-agent-sdk-demos">

56 Email assistant, research agent, and more

57 </Card>

58</CardGroup>

59 

60## Get started

61 

62<Steps>

63 <Step title="Install the SDK">

64 <Tabs>

65 <Tab title="TypeScript">

66 ```bash theme={null}

67 npm install @anthropic-ai/claude-agent-sdk

68 ```

69 </Tab>

70 

71 <Tab title="Python">

72 ```bash theme={null}

73 pip install claude-agent-sdk

74 ```

75 </Tab>

76 </Tabs>

77 

78 <Note>

79 The TypeScript SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don't need to install Claude Code separately.

80 </Note>

81 </Step>

82 

83 <Step title="Set your API key">

84 Get an API key from the [Console](https://platform.claude.com/), then set it as an environment variable:

85 

86 ```bash theme={null}

87 export ANTHROPIC_API_KEY=your-api-key

88 ```

89 

90 The SDK also supports authentication via third-party API providers:

91 

92 * **Amazon Bedrock**: set `CLAUDE_CODE_USE_BEDROCK=1` environment variable and configure AWS credentials

93 * **Google Vertex AI**: set `CLAUDE_CODE_USE_VERTEX=1` environment variable and configure Google Cloud credentials

94 * **Microsoft Azure**: set `CLAUDE_CODE_USE_FOUNDRY=1` environment variable and configure Azure credentials

95 

96 See the setup guides for [Bedrock](/en/amazon-bedrock), [Vertex AI](/en/google-vertex-ai), or [Azure AI Foundry](/en/microsoft-foundry) for details.

97 

98 <Note>

99 Unless previously approved, Anthropic does not allow third party developers to offer claude.ai login or rate limits for their products, including agents built on the Claude Agent SDK. Please use the API key authentication methods described in this document instead.

100 </Note>

101 </Step>

102 

103 <Step title="Run your first agent">

104 This example creates an agent that lists files in your current directory using built-in tools.

105 

106 <CodeGroup>

107 ```python Python theme={null}

108 import asyncio

109 from claude_agent_sdk import query, ClaudeAgentOptions

110 

111 

112 async def main():

113 async for message in query(

114 prompt="What files are in this directory?",

115 options=ClaudeAgentOptions(allowed_tools=["Bash", "Glob"]),

116 ):

117 if hasattr(message, "result"):

118 print(message.result)

119 

120 

121 asyncio.run(main())

122 ```

123 

124 ```typescript TypeScript theme={null}

125 import { query } from "@anthropic-ai/claude-agent-sdk";

126 

127 for await (const message of query({

128 prompt: "What files are in this directory?",

129 options: { allowedTools: ["Bash", "Glob"] }

130 })) {

131 if ("result" in message) console.log(message.result);

132 }

133 ```

134 </CodeGroup>

135 </Step>

136</Steps>

137 

138**Ready to build?** Follow the [Quickstart](/en/agent-sdk/quickstart) to create an agent that finds and fixes bugs in minutes.

139 

140## Capabilities

141 

142Everything that makes Claude Code powerful is available in the SDK:

143 

144<Tabs>

145 <Tab title="Built-in tools">

146 Your agent can read files, run commands, and search codebases out of the box. Key tools include:

147 

148 | Tool | What it does |

149 | --------------------------------------------------------------------------- | ------------------------------------------------------------------- |

150 | **Read** | Read any file in the working directory |

151 | **Write** | Create new files |

152 | **Edit** | Make precise edits to existing files |

153 | **Bash** | Run terminal commands, scripts, git operations |

154 | **Monitor** | Watch a background script and react to each output line as an event |

155 | **Glob** | Find files by pattern (`**/*.ts`, `src/**/*.py`) |

156 | **Grep** | Search file contents with regex |

157 | **WebSearch** | Search the web for current information |

158 | **WebFetch** | Fetch and parse web page content |

159 | **[AskUserQuestion](/en/agent-sdk/user-input#handle-clarifying-questions)** | Ask the user clarifying questions with multiple choice options |

160 

161 This example creates an agent that searches your codebase for TODO comments:

162 

163 <CodeGroup>

164 ```python Python theme={null}

165 import asyncio

166 from claude_agent_sdk import query, ClaudeAgentOptions

167 

168 

169 async def main():

170 async for message in query(

171 prompt="Find all TODO comments and create a summary",

172 options=ClaudeAgentOptions(allowed_tools=["Read", "Glob", "Grep"]),

173 ):

174 if hasattr(message, "result"):

175 print(message.result)

176 

177 

178 asyncio.run(main())

179 ```

180 

181 ```typescript TypeScript theme={null}

182 import { query } from "@anthropic-ai/claude-agent-sdk";

183 

184 for await (const message of query({

185 prompt: "Find all TODO comments and create a summary",

186 options: { allowedTools: ["Read", "Glob", "Grep"] }

187 })) {

188 if ("result" in message) console.log(message.result);

189 }

190 ```

191 </CodeGroup>

192 </Tab>

193 

194 <Tab title="Hooks">

195 Run custom code at key points in the agent lifecycle. SDK hooks use callback functions to validate, log, block, or transform agent behavior.

196 

197 **Available hooks:** `PreToolUse`, `PostToolUse`, `Stop`, `SessionStart`, `SessionEnd`, `UserPromptSubmit`, and more.

198 

199 This example logs all file changes to an audit file:

200 

201 <CodeGroup>

202 ```python Python theme={null}

203 import asyncio

204 from datetime import datetime

205 from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher

206 

207 

208 async def log_file_change(input_data, tool_use_id, context):

209 file_path = input_data.get("tool_input", {}).get("file_path", "unknown")

210 with open("./audit.log", "a") as f:

211 f.write(f"{datetime.now()}: modified {file_path}\n")

212 return {}

213 

214 

215 async def main():

216 async for message in query(

217 prompt="Refactor utils.py to improve readability",

218 options=ClaudeAgentOptions(

219 permission_mode="acceptEdits",

220 hooks={

221 "PostToolUse": [

222 HookMatcher(matcher="Edit|Write", hooks=[log_file_change])

223 ]

224 },

225 ),

226 ):

227 if hasattr(message, "result"):

228 print(message.result)

229 

230 

231 asyncio.run(main())

232 ```

233 

234 ```typescript TypeScript theme={null}

235 import { query, HookCallback } from "@anthropic-ai/claude-agent-sdk";

236 import { appendFile } from "fs/promises";

237 

238 const logFileChange: HookCallback = async (input) => {

239 const filePath = (input as any).tool_input?.file_path ?? "unknown";

240 await appendFile("./audit.log", `${new Date().toISOString()}: modified ${filePath}\n`);

241 return {};

242 };

243 

244 for await (const message of query({

245 prompt: "Refactor utils.py to improve readability",

246 options: {

247 permissionMode: "acceptEdits",

248 hooks: {

249 PostToolUse: [{ matcher: "Edit|Write", hooks: [logFileChange] }]

250 }

251 }

252 })) {

253 if ("result" in message) console.log(message.result);

254 }

255 ```

256 </CodeGroup>

257 

258 [Learn more about hooks →](/en/agent-sdk/hooks)

259 </Tab>

260 

261 <Tab title="Subagents">

262 Spawn specialized agents to handle focused subtasks. Your main agent delegates work, and subagents report back with results.

263 

264 Define custom agents with specialized instructions. Include `Agent` in `allowedTools` since subagents are invoked via the Agent tool:

265 

266 <CodeGroup>

267 ```python Python theme={null}

268 import asyncio

269 from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

270 

271 

272 async def main():

273 async for message in query(

274 prompt="Use the code-reviewer agent to review this codebase",

275 options=ClaudeAgentOptions(

276 allowed_tools=["Read", "Glob", "Grep", "Agent"],

277 agents={

278 "code-reviewer": AgentDefinition(

279 description="Expert code reviewer for quality and security reviews.",

280 prompt="Analyze code quality and suggest improvements.",

281 tools=["Read", "Glob", "Grep"],

282 )

283 },

284 ),

285 ):

286 if hasattr(message, "result"):

287 print(message.result)

288 

289 

290 asyncio.run(main())

291 ```

292 

293 ```typescript TypeScript theme={null}

294 import { query } from "@anthropic-ai/claude-agent-sdk";

295 

296 for await (const message of query({

297 prompt: "Use the code-reviewer agent to review this codebase",

298 options: {

299 allowedTools: ["Read", "Glob", "Grep", "Agent"],

300 agents: {

301 "code-reviewer": {

302 description: "Expert code reviewer for quality and security reviews.",

303 prompt: "Analyze code quality and suggest improvements.",

304 tools: ["Read", "Glob", "Grep"]

305 }

306 }

307 }

308 })) {

309 if ("result" in message) console.log(message.result);

310 }

311 ```

312 </CodeGroup>

313 

314 Messages from within a subagent's context include a `parent_tool_use_id` field, letting you track which messages belong to which subagent execution.

315 

316 [Learn more about subagents →](/en/agent-sdk/subagents)

317 </Tab>

318 

319 <Tab title="MCP">

320 Connect to external systems via the Model Context Protocol: databases, browsers, APIs, and [hundreds more](https://github.com/modelcontextprotocol/servers).

321 

322 This example connects the [Playwright MCP server](https://github.com/microsoft/playwright-mcp) to give your agent browser automation capabilities:

323 

324 <CodeGroup>

325 ```python Python theme={null}

326 import asyncio

327 from claude_agent_sdk import query, ClaudeAgentOptions

328 

329 

330 async def main():

331 async for message in query(

332 prompt="Open example.com and describe what you see",

333 options=ClaudeAgentOptions(

334 mcp_servers={

335 "playwright": {"command": "npx", "args": ["@playwright/mcp@latest"]}

336 }

337 ),

338 ):

339 if hasattr(message, "result"):

340 print(message.result)

341 

342 

343 asyncio.run(main())

344 ```

345 

346 ```typescript TypeScript theme={null}

347 import { query } from "@anthropic-ai/claude-agent-sdk";

348 

349 for await (const message of query({

350 prompt: "Open example.com and describe what you see",

351 options: {

352 mcpServers: {

353 playwright: { command: "npx", args: ["@playwright/mcp@latest"] }

354 }

355 }

356 })) {

357 if ("result" in message) console.log(message.result);

358 }

359 ```

360 </CodeGroup>

361 

362 [Learn more about MCP →](/en/agent-sdk/mcp)

363 </Tab>

364 

365 <Tab title="Permissions">

366 Control exactly which tools your agent can use. Allow safe operations, block dangerous ones, or require approval for sensitive actions.

367 

368 <Note>

369 For interactive approval prompts and the `AskUserQuestion` tool, see [Handle approvals and user input](/en/agent-sdk/user-input).

370 </Note>

371 

372 This example creates a read-only agent that can analyze but not modify code. `allowed_tools` pre-approves `Read`, `Glob`, and `Grep`.

373 

374 <CodeGroup>

375 ```python Python theme={null}

376 import asyncio

377 from claude_agent_sdk import query, ClaudeAgentOptions

378 

379 

380 async def main():

381 async for message in query(

382 prompt="Review this code for best practices",

383 options=ClaudeAgentOptions(

384 allowed_tools=["Read", "Glob", "Grep"],

385 ),

386 ):

387 if hasattr(message, "result"):

388 print(message.result)

389 

390 

391 asyncio.run(main())

392 ```

393 

394 ```typescript TypeScript theme={null}

395 import { query } from "@anthropic-ai/claude-agent-sdk";

396 

397 for await (const message of query({

398 prompt: "Review this code for best practices",

399 options: {

400 allowedTools: ["Read", "Glob", "Grep"]

401 }

402 })) {

403 if ("result" in message) console.log(message.result);

404 }

405 ```

406 </CodeGroup>

407 

408 [Learn more about permissions →](/en/agent-sdk/permissions)

409 </Tab>

410 

411 <Tab title="Sessions">

412 Maintain context across multiple exchanges. Claude remembers files read, analysis done, and conversation history. Resume sessions later, or fork them to explore different approaches.

413 

414 This example captures the session ID from the first query, then resumes to continue with full context:

415 

416 <CodeGroup>

417 ```python Python theme={null}

418 import asyncio

419 from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage, ResultMessage

420 

421 

422 async def main():

423 session_id = None

424 

425 # First query: capture the session ID

426 async for message in query(

427 prompt="Read the authentication module",

428 options=ClaudeAgentOptions(allowed_tools=["Read", "Glob"]),

429 ):

430 if isinstance(message, SystemMessage) and message.subtype == "init":

431 session_id = message.data["session_id"]

432 

433 # Resume with full context from the first query

434 async for message in query(

435 prompt="Now find all places that call it", # "it" = auth module

436 options=ClaudeAgentOptions(resume=session_id),

437 ):

438 if isinstance(message, ResultMessage):

439 print(message.result)

440 

441 

442 asyncio.run(main())

443 ```

444 

445 ```typescript TypeScript theme={null}

446 import { query } from "@anthropic-ai/claude-agent-sdk";

447 

448 let sessionId: string | undefined;

449 

450 // First query: capture the session ID

451 for await (const message of query({

452 prompt: "Read the authentication module",

453 options: { allowedTools: ["Read", "Glob"] }

454 })) {

455 if (message.type === "system" && message.subtype === "init") {

456 sessionId = message.session_id;

457 }

458 }

459 

460 // Resume with full context from the first query

461 for await (const message of query({

462 prompt: "Now find all places that call it", // "it" = auth module

463 options: { resume: sessionId }

464 })) {

465 if ("result" in message) console.log(message.result);

466 }

467 ```

468 </CodeGroup>

469 

470 [Learn more about sessions →](/en/agent-sdk/sessions)

471 </Tab>

472</Tabs>

473 

474### Claude Code features

475 

476The SDK also supports Claude Code's filesystem-based configuration. With default options the SDK loads these from `.claude/` in your working directory and `~/.claude/`. To restrict which sources load, set `setting_sources` (Python) or `settingSources` (TypeScript) in your options.

477 

478| Feature | Description | Location |

479| ------------------------------------------------ | ---------------------------------------------------- | ---------------------------------- |

480| [Skills](/en/agent-sdk/skills) | Specialized capabilities defined in Markdown | `.claude/skills/*/SKILL.md` |

481| [Slash commands](/en/agent-sdk/slash-commands) | Custom commands for common tasks | `.claude/commands/*.md` |

482| [Memory](/en/agent-sdk/modifying-system-prompts) | Project context and instructions | `CLAUDE.md` or `.claude/CLAUDE.md` |

483| [Plugins](/en/agent-sdk/plugins) | Extend with custom commands, agents, and MCP servers | Programmatic via `plugins` option |

484 

485## Compare the Agent SDK to other Claude tools

486 

487The Claude Platform offers multiple ways to build with Claude. Here's how the Agent SDK fits in:

488 

489<Tabs>

490 <Tab title="Agent SDK vs Client SDK">

491 The [Anthropic Client SDK](https://platform.claude.com/docs/en/api/client-sdks) gives you direct API access: you send prompts and implement tool execution yourself. The **Agent SDK** gives you Claude with built-in tool execution.

492 

493 With the Client SDK, you implement a tool loop. With the Agent SDK, Claude handles it:

494 

495 <CodeGroup>

496 ```python Python theme={null}

497 # Client SDK: You implement the tool loop

498 response = client.messages.create(...)

499 while response.stop_reason == "tool_use":

500 result = your_tool_executor(response.tool_use)

501 response = client.messages.create(tool_result=result, **params)

502 

503 # Agent SDK: Claude handles tools autonomously

504 async for message in query(prompt="Fix the bug in auth.py"):

505 print(message)

506 ```

507 

508 ```typescript TypeScript theme={null}

509 // Client SDK: You implement the tool loop

510 let response = await client.messages.create({ ...params });

511 while (response.stop_reason === "tool_use") {

512 const result = yourToolExecutor(response.tool_use);

513 response = await client.messages.create({ tool_result: result, ...params });

514 }

515 

516 // Agent SDK: Claude handles tools autonomously

517 for await (const message of query({ prompt: "Fix the bug in auth.ts" })) {

518 console.log(message);

519 }

520 ```

521 </CodeGroup>

522 </Tab>

523 

524 <Tab title="Agent SDK vs Claude Code CLI">

525 Same capabilities, different interface:

526 

527 | Use case | Best choice |

528 | ----------------------- | ----------- |

529 | Interactive development | CLI |

530 | CI/CD pipelines | SDK |

531 | Custom applications | SDK |

532 | One-off tasks | CLI |

533 | Production automation | SDK |

534 

535 Many teams use both: CLI for daily development, SDK for production. Workflows translate directly between them.

536 </Tab>

537</Tabs>

538 

539## Changelog

540 

541View the full changelog for SDK updates, bug fixes, and new features:

542 

543* **TypeScript SDK**: [view CHANGELOG.md](https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md)

544* **Python SDK**: [view CHANGELOG.md](https://github.com/anthropics/claude-agent-sdk-python/blob/main/CHANGELOG.md)

545 

546## Reporting bugs

547 

548If you encounter bugs or issues with the Agent SDK:

549 

550* **TypeScript SDK**: [report issues on GitHub](https://github.com/anthropics/claude-agent-sdk-typescript/issues)

551* **Python SDK**: [report issues on GitHub](https://github.com/anthropics/claude-agent-sdk-python/issues)

552 

553## Branding guidelines

554 

555For partners integrating the Claude Agent SDK, use of Claude branding is optional. When referencing Claude in your product:

556 

557**Allowed:**

558 

559* "Claude Agent" (preferred for dropdown menus)

560* "Claude" (when within a menu already labeled "Agents")

561* "{YourAgentName} Powered by Claude" (if you have an existing agent name)

562 

563**Not permitted:**

564 

565* "Claude Code" or "Claude Code Agent"

566* Claude Code-branded ASCII art or visual elements that mimic Claude Code

567 

568Your product should maintain its own branding and not appear to be Claude Code or any Anthropic product. For questions about branding compliance, contact the Anthropic [sales team](https://www.anthropic.com/contact-sales).

569 

570## License and terms

571 

572Use of the Claude Agent SDK is governed by [Anthropic's Commercial Terms of Service](https://www.anthropic.com/legal/commercial-terms), including when you use it to power products and services that you make available to your own customers and end users, except to the extent a specific component or dependency is covered by a different license as indicated in that component's LICENSE file.

573 

574## Next steps

575 

576<CardGroup cols={2}>

577 <Card title="Quickstart" icon="play" href="/en/agent-sdk/quickstart">

578 Build an agent that finds and fixes bugs in minutes

579 </Card>

580 

581 <Card title="Example agents" icon="star" href="https://github.com/anthropics/claude-agent-sdk-demos">

582 Email assistant, research agent, and more

583 </Card>

584 

585 <Card title="TypeScript SDK" icon="code" href="/en/agent-sdk/typescript">

586 Full TypeScript API reference and examples

587 </Card>

588 

589 <Card title="Python SDK" icon="code" href="/en/agent-sdk/python">

590 Full Python API reference and examples

591 </Card>

592</CardGroup>

agent-sdk/permissions.md +242 −0 added

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# Configure permissions

6 

7> Control how your agent uses tools with permission modes, hooks, and declarative allow/deny rules.

8 

9The Claude Agent SDK provides permission controls to manage how Claude uses tools. Use permission modes and rules to define what's allowed automatically, and the [`canUseTool` callback](/en/agent-sdk/user-input) to handle everything else at runtime.

10 

11<Note>

12 This page covers permission modes and rules. To build interactive approval flows where users approve or deny tool requests at runtime, see [Handle approvals and user input](/en/agent-sdk/user-input).

13</Note>

14 

15## How permissions are evaluated

16 

17When Claude requests a tool, the SDK checks permissions in this order:

18 

19<Steps>

20 <Step title="Hooks">

21 Run [hooks](/en/agent-sdk/hooks) first, which can allow, deny, or continue to the next step

22 </Step>

23 

24 <Step title="Deny rules">

25 Check `deny` rules (from `disallowed_tools` and [settings.json](/en/settings#permission-settings)). If a deny rule matches, the tool is blocked, even in `bypassPermissions` mode.

26 </Step>

27 

28 <Step title="Permission mode">

29 Apply the active [permission mode](#permission-modes). `bypassPermissions` approves everything that reaches this step. `acceptEdits` approves file operations. Other modes fall through.

30 </Step>

31 

32 <Step title="Allow rules">

33 Check `allow` rules (from `allowed_tools` and settings.json). If a rule matches, the tool is approved.

34 </Step>

35 

36 <Step title="canUseTool callback">

37 If not resolved by any of the above, call your [`canUseTool` callback](/en/agent-sdk/user-input) for a decision. In `dontAsk` mode, this step is skipped and the tool is denied.

38 </Step>

39</Steps>

40 

41<img src="https://mintcdn.com/claude-code/gvy2DIUELtNA8qD3/images/agent-sdk/permissions-flow.svg?fit=max&auto=format&n=gvy2DIUELtNA8qD3&q=85&s=0ccd63043a9ffc2a34d863602e043f72" alt="Permission evaluation flow diagram" width="920" height="260" data-path="images/agent-sdk/permissions-flow.svg" />

42 

43This page focuses on **allow and deny rules** and **permission modes**. For the other steps:

44 

45* **Hooks:** run custom code to allow, deny, or modify tool requests. See [Control execution with hooks](/en/agent-sdk/hooks).

46* **canUseTool callback:** prompt users for approval at runtime. See [Handle approvals and user input](/en/agent-sdk/user-input).

47 

48## Allow and deny rules

49 

50`allowed_tools` and `disallowed_tools` (TypeScript: `allowedTools` / `disallowedTools`) add entries to the allow and deny rule lists in the evaluation flow above. They control whether a tool call is approved, not whether the tool is available to Claude.

51 

52| Option | Effect |

53| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- |

54| `allowed_tools=["Read", "Grep"]` | `Read` and `Grep` are auto-approved. Tools not listed here still exist and fall through to the permission mode and `canUseTool`. |

55| `disallowed_tools=["Bash"]` | `Bash` is always denied. Deny rules are checked first and hold in every permission mode, including `bypassPermissions`. |

56 

57For a locked-down agent, pair `allowedTools` with `permissionMode: "dontAsk"`. Listed tools are approved; anything else is denied outright instead of prompting:

58 

59```typescript theme={null}

60const options = {

61 allowedTools: ["Read", "Glob", "Grep"],

62 permissionMode: "dontAsk"

63};

64```

65 

66<Warning>

67 **`allowed_tools` does not constrain `bypassPermissions`.** `allowed_tools` only pre-approves the tools you list. Unlisted tools are not matched by any allow rule and fall through to the permission mode, where `bypassPermissions` approves them. Setting `allowed_tools=["Read"]` alongside `permission_mode="bypassPermissions"` still approves every tool, including `Bash`, `Write`, and `Edit`. If you need `bypassPermissions` but want specific tools blocked, use `disallowed_tools`.

68</Warning>

69 

70You can also configure allow, deny, and ask rules declaratively in `.claude/settings.json`. These rules are read when the `project` setting source is enabled, which it is for default `query()` options. If you set `setting_sources` (TypeScript: `settingSources`) explicitly, include `"project"` for them to apply. See [Permission settings](/en/settings#permission-settings) for the rule syntax.

71 

72## Permission modes

73 

74Permission modes provide global control over how Claude uses tools. You can set the permission mode when calling `query()` or change it dynamically during streaming sessions.

75 

76### Available modes

77 

78The SDK supports these permission modes:

79 

80| Mode | Description | Tool behavior |

81| :----------------------- | :--------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |

82| `default` | Standard permission behavior | No auto-approvals; unmatched tools trigger your `canUseTool` callback |

83| `dontAsk` | Deny instead of prompting | Anything not pre-approved by `allowed_tools` or rules is denied; `canUseTool` is never called |

84| `acceptEdits` | Auto-accept file edits | File edits and [filesystem operations](#accept-edits-mode-acceptedits) (`mkdir`, `rm`, `mv`, etc.) are automatically approved |

85| `bypassPermissions` | Bypass all permission checks | All tools run without permission prompts (use with caution) |

86| `plan` | Planning mode | No tool execution; Claude plans without making changes |

87| `auto` (TypeScript only) | Model-classified approvals | A model classifier approves or denies each tool call. See [Auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) for availability |

88 

89<Warning>

90 **Subagent inheritance:** When the parent uses `bypassPermissions`, `acceptEdits`, or `auto`, all subagents inherit that mode and it cannot be overridden per subagent. Subagents may have different system prompts and less constrained behavior than your main agent, so inheriting `bypassPermissions` grants them full, autonomous system access without any approval prompts.

91</Warning>

92 

93### Set permission mode

94 

95You can set the permission mode once when starting a query, or change it dynamically while the session is active.

96 

97<Tabs>

98 <Tab title="At query time">

99 Pass `permission_mode` (Python) or `permissionMode` (TypeScript) when creating a query. This mode applies for the entire session unless changed dynamically.

100 

101 <CodeGroup>

102 ```python Python theme={null}

103 import asyncio

104 from claude_agent_sdk import query, ClaudeAgentOptions

105 

106 

107 async def main():

108 async for message in query(

109 prompt="Help me refactor this code",

110 options=ClaudeAgentOptions(

111 permission_mode="default", # Set the mode here

112 ),

113 ):

114 if hasattr(message, "result"):

115 print(message.result)

116 

117 

118 asyncio.run(main())

119 ```

120 

121 ```typescript TypeScript theme={null}

122 import { query } from "@anthropic-ai/claude-agent-sdk";

123 

124 async function main() {

125 for await (const message of query({

126 prompt: "Help me refactor this code",

127 options: {

128 permissionMode: "default" // Set the mode here

129 }

130 })) {

131 if ("result" in message) {

132 console.log(message.result);

133 }

134 }

135 }

136 

137 main();

138 ```

139 </CodeGroup>

140 </Tab>

141 

142 <Tab title="During streaming">

143 Call `set_permission_mode()` (Python) or `setPermissionMode()` (TypeScript) to change the mode mid-session. The new mode takes effect immediately for all subsequent tool requests. This lets you start restrictive and loosen permissions as trust builds, for example switching to `acceptEdits` after reviewing Claude's initial approach.

144 

145 <CodeGroup>

146 ```python Python theme={null}

147 import asyncio

148 from claude_agent_sdk import query, ClaudeAgentOptions

149 

150 

151 async def main():

152 q = query(

153 prompt="Help me refactor this code",

154 options=ClaudeAgentOptions(

155 permission_mode="default", # Start in default mode

156 ),

157 )

158 

159 # Change mode dynamically mid-session

160 await q.set_permission_mode("acceptEdits")

161 

162 # Process messages with the new permission mode

163 async for message in q:

164 if hasattr(message, "result"):

165 print(message.result)

166 

167 

168 asyncio.run(main())

169 ```

170 

171 ```typescript TypeScript theme={null}

172 import { query } from "@anthropic-ai/claude-agent-sdk";

173 

174 async function main() {

175 const q = query({

176 prompt: "Help me refactor this code",

177 options: {

178 permissionMode: "default" // Start in default mode

179 }

180 });

181 

182 // Change mode dynamically mid-session

183 await q.setPermissionMode("acceptEdits");

184 

185 // Process messages with the new permission mode

186 for await (const message of q) {

187 if ("result" in message) {

188 console.log(message.result);

189 }

190 }

191 }

192 

193 main();

194 ```

195 </CodeGroup>

196 </Tab>

197</Tabs>

198 

199### Mode details

200 

201#### Accept edits mode (`acceptEdits`)

202 

203Auto-approves file operations so Claude can edit code without prompting. Other tools (like Bash commands that aren't filesystem operations) still require normal permissions.

204 

205**Auto-approved operations:**

206 

207* File edits (Edit, Write tools)

208* Filesystem commands: `mkdir`, `touch`, `rm`, `rmdir`, `mv`, `cp`, `sed`

209 

210Both apply only to paths inside the working directory or `additionalDirectories`. Paths outside that scope and writes to protected paths still prompt.

211 

212**Use when:** you trust Claude's edits and want faster iteration, such as during prototyping or when working in an isolated directory.

213 

214#### Don't ask mode (`dontAsk`)

215 

216Converts any permission prompt into a denial. Tools pre-approved by `allowed_tools`, `settings.json` allow rules, or a hook run as normal. Everything else is denied without calling `canUseTool`.

217 

218**Use when:** you want a fixed, explicit tool surface for a headless agent and prefer a hard deny over silent reliance on `canUseTool` being absent.

219 

220#### Bypass permissions mode (`bypassPermissions`)

221 

222Auto-approves all tool uses without prompts. Hooks still execute and can block operations if needed.

223 

224<Warning>

225 Use with extreme caution. Claude has full system access in this mode. Only use in controlled environments where you trust all possible operations.

226 

227 `allowed_tools` does not constrain this mode. Every tool is approved, not just the ones you listed. Deny rules (`disallowed_tools`), explicit `ask` rules, and hooks are evaluated before the mode check and can still block a tool.

228</Warning>

229 

230#### Plan mode (`plan`)

231 

232Prevents tool execution entirely. Claude can analyze code and create plans but cannot make changes. Claude may use `AskUserQuestion` to clarify requirements before finalizing the plan. See [Handle approvals and user input](/en/agent-sdk/user-input#handle-clarifying-questions) for handling these prompts.

233 

234**Use when:** you want Claude to propose changes without executing them, such as during code review or when you need to approve changes before they're made.

235 

236## Related resources

237 

238For the other steps in the permission evaluation flow:

239 

240* [Handle approvals and user input](/en/agent-sdk/user-input): interactive approval prompts and clarifying questions

241* [Hooks guide](/en/agent-sdk/hooks): run custom code at key points in the agent lifecycle

242* [Permission rules](/en/settings#permission-settings): declarative allow/deny rules in `settings.json`

agent-sdk/plugins.md +342 −0 added

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# Plugins in the SDK

6 

7> Load custom plugins to extend Claude Code with commands, agents, skills, and hooks through the Agent SDK

8 

9Plugins allow you to extend Claude Code with custom functionality that can be shared across projects. Through the Agent SDK, you can programmatically load plugins from local directories to add custom slash commands, agents, skills, hooks, and MCP servers to your agent sessions.

10 

11## What are plugins?

12 

13Plugins are packages of Claude Code extensions that can include:

14 

15* **Skills**: Model-invoked capabilities that Claude uses autonomously (can also be invoked with `/skill-name`)

16* **Agents**: Specialized subagents for specific tasks

17* **Hooks**: Event handlers that respond to tool use and other events

18* **MCP servers**: External tool integrations via Model Context Protocol

19 

20<Note>

21 The `commands/` directory is a legacy format. Use `skills/` for new plugins. Claude Code continues to support both formats for backward compatibility.

22</Note>

23 

24For complete information on plugin structure and how to create plugins, see [Plugins](/en/plugins).

25 

26## Loading plugins

27 

28Load plugins by providing their local file system paths in your options configuration. The SDK supports loading multiple plugins from different locations.

29 

30<CodeGroup>

31 ```typescript TypeScript theme={null}

32 import { query } from "@anthropic-ai/claude-agent-sdk";

33 

34 for await (const message of query({

35 prompt: "Hello",

36 options: {

37 plugins: [

38 { type: "local", path: "./my-plugin" },

39 { type: "local", path: "/absolute/path/to/another-plugin" }

40 ]

41 }

42 })) {

43 // Plugin commands, agents, and other features are now available

44 }

45 ```

46 

47 ```python Python theme={null}

48 import asyncio

49 from claude_agent_sdk import query

50 

51 

52 async def main():

53 async for message in query(

54 prompt="Hello",

55 options={

56 "plugins": [

57 {"type": "local", "path": "./my-plugin"},

58 {"type": "local", "path": "/absolute/path/to/another-plugin"},

59 ]

60 },

61 ):

62 # Plugin commands, agents, and other features are now available

63 pass

64 

65 

66 asyncio.run(main())

67 ```

68</CodeGroup>

69 

70### Path specifications

71 

72Plugin paths can be:

73 

74* **Relative paths**: Resolved relative to your current working directory (for example, `"./plugins/my-plugin"`)

75* **Absolute paths**: Full file system paths (for example, `"/home/user/plugins/my-plugin"`)

76 

77<Note>

78 The path should point to the plugin's root directory (the directory containing `.claude-plugin/plugin.json`).

79</Note>

80 

81## Verifying plugin installation

82 

83When plugins load successfully, they appear in the system initialization message. You can verify that your plugins are available:

84 

85<CodeGroup>

86 ```typescript TypeScript theme={null}

87 import { query } from "@anthropic-ai/claude-agent-sdk";

88 

89 for await (const message of query({

90 prompt: "Hello",

91 options: {

92 plugins: [{ type: "local", path: "./my-plugin" }]

93 }

94 })) {

95 if (message.type === "system" && message.subtype === "init") {

96 // Check loaded plugins

97 console.log("Plugins:", message.plugins);

98 // Example: [{ name: "my-plugin", path: "./my-plugin" }]

99 

100 // Check available commands from plugins

101 console.log("Commands:", message.slash_commands);

102 // Example: ["/help", "/compact", "my-plugin:custom-command"]

103 }

104 }

105 ```

106 

107 ```python Python theme={null}

108 import asyncio

109 from claude_agent_sdk import query

110 

111 

112 async def main():

113 async for message in query(

114 prompt="Hello", options={"plugins": [{"type": "local", "path": "./my-plugin"}]}

115 ):

116 if message.type == "system" and message.subtype == "init":

117 # Check loaded plugins

118 print("Plugins:", message.data.get("plugins"))

119 # Example: [{"name": "my-plugin", "path": "./my-plugin"}]

120 

121 # Check available commands from plugins

122 print("Commands:", message.data.get("slash_commands"))

123 # Example: ["/help", "/compact", "my-plugin:custom-command"]

124 

125 

126 asyncio.run(main())

127 ```

128</CodeGroup>

129 

130## Using plugin skills

131 

132Skills from plugins are automatically namespaced with the plugin name to avoid conflicts. When invoked as slash commands, the format is `plugin-name:skill-name`.

133 

134<CodeGroup>

135 ```typescript TypeScript theme={null}

136 import { query } from "@anthropic-ai/claude-agent-sdk";

137 

138 // Load a plugin with a custom /greet skill

139 for await (const message of query({

140 prompt: "/my-plugin:greet", // Use plugin skill with namespace

141 options: {

142 plugins: [{ type: "local", path: "./my-plugin" }]

143 }

144 })) {

145 // Claude executes the custom greeting skill from the plugin

146 if (message.type === "assistant") {

147 console.log(message.message.content);

148 }

149 }

150 ```

151 

152 ```python Python theme={null}

153 import asyncio

154 from claude_agent_sdk import query, AssistantMessage, TextBlock

155 

156 

157 async def main():

158 # Load a plugin with a custom /greet skill

159 async for message in query(

160 prompt="/demo-plugin:greet", # Use plugin skill with namespace

161 options={"plugins": [{"type": "local", "path": "./plugins/demo-plugin"}]},

162 ):

163 # Claude executes the custom greeting skill from the plugin

164 if isinstance(message, AssistantMessage):

165 for block in message.content:

166 if isinstance(block, TextBlock):

167 print(f"Claude: {block.text}")

168 

169 

170 asyncio.run(main())

171 ```

172</CodeGroup>

173 

174<Note>

175 If you installed a plugin via the CLI (for example, `/plugin install my-plugin@marketplace`), you can still use it in the SDK by providing its installation path. Check `~/.claude/plugins/` for CLI-installed plugins.

176</Note>

177 

178## Complete example

179 

180Here's a full example demonstrating plugin loading and usage:

181 

182<CodeGroup>

183 ```typescript TypeScript theme={null}

184 import { query } from "@anthropic-ai/claude-agent-sdk";

185 import * as path from "path";

186 

187 async function runWithPlugin() {

188 const pluginPath = path.join(__dirname, "plugins", "my-plugin");

189 

190 console.log("Loading plugin from:", pluginPath);

191 

192 for await (const message of query({

193 prompt: "What custom commands do you have available?",

194 options: {

195 plugins: [{ type: "local", path: pluginPath }],

196 maxTurns: 3

197 }

198 })) {

199 if (message.type === "system" && message.subtype === "init") {

200 console.log("Loaded plugins:", message.plugins);

201 console.log("Available commands:", message.slash_commands);

202 }

203 

204 if (message.type === "assistant") {

205 console.log("Assistant:", message.message.content);

206 }

207 }

208 }

209 

210 runWithPlugin().catch(console.error);

211 ```

212 

213 ```python Python theme={null}

214 #!/usr/bin/env python3

215 """Example demonstrating how to use plugins with the Agent SDK."""

216 

217 from pathlib import Path

218 import anyio

219 from claude_agent_sdk import (

220 AssistantMessage,

221 ClaudeAgentOptions,

222 TextBlock,

223 query,

224 )

225 

226 

227 async def run_with_plugin():

228 """Example using a custom plugin."""

229 plugin_path = Path(__file__).parent / "plugins" / "demo-plugin"

230 

231 print(f"Loading plugin from: {plugin_path}")

232 

233 options = ClaudeAgentOptions(

234 plugins=[{"type": "local", "path": str(plugin_path)}],

235 max_turns=3,

236 )

237 

238 async for message in query(

239 prompt="What custom commands do you have available?", options=options

240 ):

241 if message.type == "system" and message.subtype == "init":

242 print(f"Loaded plugins: {message.data.get('plugins')}")

243 print(f"Available commands: {message.data.get('slash_commands')}")

244 

245 if isinstance(message, AssistantMessage):

246 for block in message.content:

247 if isinstance(block, TextBlock):

248 print(f"Assistant: {block.text}")

249 

250 

251 if __name__ == "__main__":

252 anyio.run(run_with_plugin)

253 ```

254</CodeGroup>

255 

256## Plugin structure reference

257 

258A plugin directory must contain a `.claude-plugin/plugin.json` manifest file. It can optionally include:

259 

260```text theme={null}

261my-plugin/

262├── .claude-plugin/

263│ └── plugin.json # Required: plugin manifest

264├── skills/ # Agent Skills (invoked autonomously or via /skill-name)

265│ └── my-skill/

266│ └── SKILL.md

267├── commands/ # Legacy: use skills/ instead

268│ └── custom-cmd.md

269├── agents/ # Custom agents

270│ └── specialist.md

271├── hooks/ # Event handlers

272│ └── hooks.json

273└── .mcp.json # MCP server definitions

274```

275 

276For detailed information on creating plugins, see:

277 

278* [Plugins](/en/plugins) - Complete plugin development guide

279* [Plugins reference](/en/plugins-reference) - Technical specifications and schemas

280 

281## Common use cases

282 

283### Development and testing

284 

285Load plugins during development without installing them globally:

286 

287```typescript theme={null}

288plugins: [{ type: "local", path: "./dev-plugins/my-plugin" }];

289```

290 

291### Project-specific extensions

292 

293Include plugins in your project repository for team-wide consistency:

294 

295```typescript theme={null}

296plugins: [{ type: "local", path: "./project-plugins/team-workflows" }];

297```

298 

299### Multiple plugin sources

300 

301Combine plugins from different locations:

302 

303```typescript theme={null}

304plugins: [

305 { type: "local", path: "./local-plugin" },

306 { type: "local", path: "~/.claude/custom-plugins/shared-plugin" }

307];

308```

309 

310## Troubleshooting

311 

312### Plugin not loading

313 

314If your plugin doesn't appear in the init message:

315 

3161. **Check the path**: Ensure the path points to the plugin root directory (containing `.claude-plugin/`)

3172. **Validate plugin.json**: Ensure your manifest file has valid JSON syntax

3183. **Check file permissions**: Ensure the plugin directory is readable

319 

320### Skills not appearing

321 

322If plugin skills don't work:

323 

3241. **Use the namespace**: Plugin skills require the `plugin-name:skill-name` format when invoked as slash commands

3252. **Check init message**: Verify the skill appears in `slash_commands` with the correct namespace

3263. **Validate skill files**: Ensure each skill has a `SKILL.md` file in its own subdirectory under `skills/` (for example, `skills/my-skill/SKILL.md`)

327 

328### Path resolution issues

329 

330If relative paths don't work:

331 

3321. **Check working directory**: Relative paths are resolved from your current working directory

3332. **Use absolute paths**: For reliability, consider using absolute paths

3343. **Normalize paths**: Use path utilities to construct paths correctly

335 

336## See also

337 

338* [Plugins](/en/plugins) - Complete plugin development guide

339* [Plugins reference](/en/plugins-reference) - Technical specifications

340* [Slash Commands](/en/agent-sdk/slash-commands) - Using slash commands in the SDK

341* [Subagents](/en/agent-sdk/subagents) - Working with specialized agents

342* [Skills](/en/agent-sdk/skills) - Using Agent Skills

agent-sdk/python.md +3272 −0 added

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# Agent SDK reference - Python

6 

7> Complete API reference for the Python Agent SDK, including all functions, types, and classes.

8 

9## Installation

10 

11```bash theme={null}

12pip install claude-agent-sdk

13```

14 

15## Choosing between `query()` and `ClaudeSDKClient`

16 

17The Python SDK provides two ways to interact with Claude Code:

18 

19### Quick comparison

20 

21| Feature | `query()` | `ClaudeSDKClient` |

22| :------------------ | :---------------------------- | :--------------------------------- |

23| **Session** | Creates new session each time | Reuses same session |

24| **Conversation** | Single exchange | Multiple exchanges in same context |

25| **Connection** | Managed automatically | Manual control |

26| **Streaming Input** | ✅ Supported | ✅ Supported |

27| **Interrupts** | ❌ Not supported | ✅ Supported |

28| **Hooks** | ✅ Supported | ✅ Supported |

29| **Custom Tools** | ✅ Supported | ✅ Supported |

30| **Continue Chat** | ❌ New session each time | ✅ Maintains conversation |

31| **Use Case** | One-off tasks | Continuous conversations |

32 

33### When to use `query()` (new session each time)

34 

35**Best for:**

36 

37* One-off questions where you don't need conversation history

38* Independent tasks that don't require context from previous exchanges

39* Simple automation scripts

40* When you want a fresh start each time

41 

42### When to use `ClaudeSDKClient` (continuous conversation)

43 

44**Best for:**

45 

46* **Continuing conversations** - When you need Claude to remember context

47* **Follow-up questions** - Building on previous responses

48* **Interactive applications** - Chat interfaces, REPLs

49* **Response-driven logic** - When next action depends on Claude's response

50* **Session control** - Managing conversation lifecycle explicitly

51 

52## Functions

53 

54### `query()`

55 

56Creates a new session for each interaction with Claude Code. Returns an async iterator that yields messages as they arrive. Each call to `query()` starts fresh with no memory of previous interactions.

57 

58```python theme={null}

59async def query(

60 *,

61 prompt: str | AsyncIterable[dict[str, Any]],

62 options: ClaudeAgentOptions | None = None,

63 transport: Transport | None = None

64) -> AsyncIterator[Message]

65```

66 

67#### Parameters

68 

69| Parameter | Type | Description |

70| :---------- | :--------------------------- | :------------------------------------------------------------------------- |

71| `prompt` | `str \| AsyncIterable[dict]` | The input prompt as a string or async iterable for streaming mode |

72| `options` | `ClaudeAgentOptions \| None` | Optional configuration object (defaults to `ClaudeAgentOptions()` if None) |

73| `transport` | `Transport \| None` | Optional custom transport for communicating with the CLI process |

74 

75#### Returns

76 

77Returns an `AsyncIterator[Message]` that yields messages from the conversation.

78 

79#### Example - With options

80 

81```python theme={null}

82import asyncio

83from claude_agent_sdk import query, ClaudeAgentOptions

84 

85 

86async def main():

87 options = ClaudeAgentOptions(

88 system_prompt="You are an expert Python developer",

89 permission_mode="acceptEdits",

90 cwd="/home/user/project",

91 )

92 

93 async for message in query(prompt="Create a Python web server", options=options):

94 print(message)

95 

96 

97asyncio.run(main())

98```

99 

100### `tool()`

101 

102Decorator for defining MCP tools with type safety.

103 

104```python theme={null}

105def tool(

106 name: str,

107 description: str,

108 input_schema: type | dict[str, Any],

109 annotations: ToolAnnotations | None = None

110) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]

111```

112 

113#### Parameters

114 

115| Parameter | Type | Description |

116| :------------- | :----------------------------------------------- | :------------------------------------------------------------------ |

117| `name` | `str` | Unique identifier for the tool |

118| `description` | `str` | Human-readable description of what the tool does |

119| `input_schema` | `type \| dict[str, Any]` | Schema defining the tool's input parameters (see below) |

120| `annotations` | [`ToolAnnotations`](#tool-annotations)` \| None` | Optional MCP tool annotations providing behavioral hints to clients |

121 

122#### Input schema options

123 

1241. **Simple type mapping** (recommended):

125 

126 ```python theme={null}

127 {"text": str, "count": int, "enabled": bool}

128 ```

129 

1302. **JSON Schema format** (for complex validation):

131 ```python theme={null}

132 {

133 "type": "object",

134 "properties": {

135 "text": {"type": "string"},

136 "count": {"type": "integer", "minimum": 0},

137 },

138 "required": ["text"],

139 }

140 ```

141 

142#### Returns

143 

144A decorator function that wraps the tool implementation and returns an `SdkMcpTool` instance.

145 

146#### Example

147 

148```python theme={null}

149from claude_agent_sdk import tool

150from typing import Any

151 

152 

153@tool("greet", "Greet a user", {"name": str})

154async def greet(args: dict[str, Any]) -> dict[str, Any]:

155 return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}

156```

157 

158#### `ToolAnnotations`

159 

160Re-exported from `mcp.types` (also available as `from claude_agent_sdk import ToolAnnotations`). All fields are optional hints; clients should not rely on them for security decisions.

161 

162| Field | Type | Default | Description |

163| :---------------- | :------------- | :------ | :--------------------------------------------------------------------------------------------------------------------------------------------------- |

164| `title` | `str \| None` | `None` | Human-readable title for the tool |

165| `readOnlyHint` | `bool \| None` | `False` | If `True`, the tool does not modify its environment |

166| `destructiveHint` | `bool \| None` | `True` | If `True`, the tool may perform destructive updates (only meaningful when `readOnlyHint` is `False`) |

167| `idempotentHint` | `bool \| None` | `False` | If `True`, repeated calls with the same arguments have no additional effect (only meaningful when `readOnlyHint` is `False`) |

168| `openWorldHint` | `bool \| None` | `True` | If `True`, the tool interacts with external entities (for example, web search). If `False`, the tool's domain is closed (for example, a memory tool) |

169 

170```python theme={null}

171from claude_agent_sdk import tool, ToolAnnotations

172from typing import Any

173 

174 

175@tool(

176 "search",

177 "Search the web",

178 {"query": str},

179 annotations=ToolAnnotations(readOnlyHint=True, openWorldHint=True),

180)

181async def search(args: dict[str, Any]) -> dict[str, Any]:

182 return {"content": [{"type": "text", "text": f"Results for: {args['query']}"}]}

183```

184 

185### `create_sdk_mcp_server()`

186 

187Create an in-process MCP server that runs within your Python application.

188 

189```python theme={null}

190def create_sdk_mcp_server(

191 name: str,

192 version: str = "1.0.0",

193 tools: list[SdkMcpTool[Any]] | None = None

194) -> McpSdkServerConfig

195```

196 

197#### Parameters

198 

199| Parameter | Type | Default | Description |

200| :-------- | :------------------------------ | :-------- | :---------------------------------------------------- |

201| `name` | `str` | - | Unique identifier for the server |

202| `version` | `str` | `"1.0.0"` | Server version string |

203| `tools` | `list[SdkMcpTool[Any]] \| None` | `None` | List of tool functions created with `@tool` decorator |

204 

205#### Returns

206 

207Returns an `McpSdkServerConfig` object that can be passed to `ClaudeAgentOptions.mcp_servers`.

208 

209#### Example

210 

211```python theme={null}

212from claude_agent_sdk import tool, create_sdk_mcp_server

213 

214 

215@tool("add", "Add two numbers", {"a": float, "b": float})

216async def add(args):

217 return {"content": [{"type": "text", "text": f"Sum: {args['a'] + args['b']}"}]}

218 

219 

220@tool("multiply", "Multiply two numbers", {"a": float, "b": float})

221async def multiply(args):

222 return {"content": [{"type": "text", "text": f"Product: {args['a'] * args['b']}"}]}

223 

224 

225calculator = create_sdk_mcp_server(

226 name="calculator",

227 version="2.0.0",

228 tools=[add, multiply], # Pass decorated functions

229)

230 

231# Use with Claude

232options = ClaudeAgentOptions(

233 mcp_servers={"calc": calculator},

234 allowed_tools=["mcp__calc__add", "mcp__calc__multiply"],

235)

236```

237 

238### `list_sessions()`

239 

240Lists past sessions with metadata. Filter by project directory or list sessions across all projects. Synchronous; returns immediately.

241 

242```python theme={null}

243def list_sessions(

244 directory: str | None = None,

245 limit: int | None = None,

246 include_worktrees: bool = True

247) -> list[SDKSessionInfo]

248```

249 

250#### Parameters

251 

252| Parameter | Type | Default | Description |

253| :------------------ | :------------ | :------ | :------------------------------------------------------------------------------------ |

254| `directory` | `str \| None` | `None` | Directory to list sessions for. When omitted, returns sessions across all projects |

255| `limit` | `int \| None` | `None` | Maximum number of sessions to return |

256| `include_worktrees` | `bool` | `True` | When `directory` is inside a git repository, include sessions from all worktree paths |

257 

258#### Return type: `SDKSessionInfo`

259 

260| Property | Type | Description |

261| :-------------- | :------------ | :------------------------------------------------------------------- |

262| `session_id` | `str` | Unique session identifier |

263| `summary` | `str` | Display title: custom title, auto-generated summary, or first prompt |

264| `last_modified` | `int` | Last modified time in milliseconds since epoch |

265| `file_size` | `int \| None` | Session file size in bytes (`None` for remote storage backends) |

266| `custom_title` | `str \| None` | User-set session title |

267| `first_prompt` | `str \| None` | First meaningful user prompt in the session |

268| `git_branch` | `str \| None` | Git branch at the end of the session |

269| `cwd` | `str \| None` | Working directory for the session |

270| `tag` | `str \| None` | User-set session tag (see [`tag_session()`](#tag-session)) |

271| `created_at` | `int \| None` | Session creation time in milliseconds since epoch |

272 

273#### Example

274 

275Print the 10 most recent sessions for a project. Results are sorted by `last_modified` descending, so the first item is the newest. Omit `directory` to search across all projects.

276 

277```python theme={null}

278from claude_agent_sdk import list_sessions

279 

280for session in list_sessions(directory="/path/to/project", limit=10):

281 print(f"{session.summary} ({session.session_id})")

282```

283 

284### `get_session_messages()`

285 

286Retrieves messages from a past session. Synchronous; returns immediately.

287 

288```python theme={null}

289def get_session_messages(

290 session_id: str,

291 directory: str | None = None,

292 limit: int | None = None,

293 offset: int = 0

294) -> list[SessionMessage]

295```

296 

297#### Parameters

298 

299| Parameter | Type | Default | Description |

300| :----------- | :------------ | :------- | :---------------------------------------------------------------- |

301| `session_id` | `str` | required | The session ID to retrieve messages for |

302| `directory` | `str \| None` | `None` | Project directory to look in. When omitted, searches all projects |

303| `limit` | `int \| None` | `None` | Maximum number of messages to return |

304| `offset` | `int` | `0` | Number of messages to skip from the start |

305 

306#### Return type: `SessionMessage`

307 

308| Property | Type | Description |

309| :------------------- | :----------------------------- | :------------------------ |

310| `type` | `Literal["user", "assistant"]` | Message role |

311| `uuid` | `str` | Unique message identifier |

312| `session_id` | `str` | Session identifier |

313| `message` | `Any` | Raw message content |

314| `parent_tool_use_id` | `None` | Reserved for future use |

315 

316#### Example

317 

318```python theme={null}

319from claude_agent_sdk import list_sessions, get_session_messages

320 

321sessions = list_sessions(limit=1)

322if sessions:

323 messages = get_session_messages(sessions[0].session_id)

324 for msg in messages:

325 print(f"[{msg.type}] {msg.uuid}")

326```

327 

328### `get_session_info()`

329 

330Reads metadata for a single session by ID without scanning the full project directory. Synchronous; returns immediately.

331 

332```python theme={null}

333def get_session_info(

334 session_id: str,

335 directory: str | None = None,

336) -> SDKSessionInfo | None

337```

338 

339#### Parameters

340 

341| Parameter | Type | Default | Description |

342| :----------- | :------------ | :------- | :--------------------------------------------------------------------- |

343| `session_id` | `str` | required | UUID of the session to look up |

344| `directory` | `str \| None` | `None` | Project directory path. When omitted, searches all project directories |

345 

346Returns [`SDKSessionInfo`](#return-type-sdk-session-info), or `None` if the session is not found.

347 

348#### Example

349 

350Look up a single session's metadata without scanning the project directory. Useful when you already have a session ID from a previous run.

351 

352```python theme={null}

353from claude_agent_sdk import get_session_info

354 

355info = get_session_info("550e8400-e29b-41d4-a716-446655440000")

356if info:

357 print(f"{info.summary} (branch: {info.git_branch}, tag: {info.tag})")

358```

359 

360### `rename_session()`

361 

362Renames a session by appending a custom-title entry. Repeated calls are safe; the most recent title wins. Synchronous.

363 

364```python theme={null}

365def rename_session(

366 session_id: str,

367 title: str,

368 directory: str | None = None,

369) -> None

370```

371 

372#### Parameters

373 

374| Parameter | Type | Default | Description |

375| :----------- | :------------ | :------- | :--------------------------------------------------------------------- |

376| `session_id` | `str` | required | UUID of the session to rename |

377| `title` | `str` | required | New title. Must be non-empty after stripping whitespace |

378| `directory` | `str \| None` | `None` | Project directory path. When omitted, searches all project directories |

379 

380Raises `ValueError` if `session_id` is not a valid UUID or `title` is empty; `FileNotFoundError` if the session cannot be found.

381 

382#### Example

383 

384Rename the most recent session so it's easier to find later. The new title appears in [`SDKSessionInfo.custom_title`](#return-type-sdk-session-info) on subsequent reads.

385 

386```python theme={null}

387from claude_agent_sdk import list_sessions, rename_session

388 

389sessions = list_sessions(directory="/path/to/project", limit=1)

390if sessions:

391 rename_session(sessions[0].session_id, "Refactor auth module")

392```

393 

394### `tag_session()`

395 

396Tags a session. Pass `None` to clear the tag. Repeated calls are safe; the most recent tag wins. Synchronous.

397 

398```python theme={null}

399def tag_session(

400 session_id: str,

401 tag: str | None,

402 directory: str | None = None,

403) -> None

404```

405 

406#### Parameters

407 

408| Parameter | Type | Default | Description |

409| :----------- | :------------ | :------- | :--------------------------------------------------------------------- |

410| `session_id` | `str` | required | UUID of the session to tag |

411| `tag` | `str \| None` | required | Tag string, or `None` to clear. Unicode-sanitized before storing |

412| `directory` | `str \| None` | `None` | Project directory path. When omitted, searches all project directories |

413 

414Raises `ValueError` if `session_id` is not a valid UUID or `tag` is empty after sanitization; `FileNotFoundError` if the session cannot be found.

415 

416#### Example

417 

418Tag a session, then filter by that tag on a later read. Pass `None` to clear an existing tag.

419 

420```python theme={null}

421from claude_agent_sdk import list_sessions, tag_session

422 

423# Tag a session

424tag_session("550e8400-e29b-41d4-a716-446655440000", "needs-review")

425 

426# Later: find all sessions with that tag

427for session in list_sessions(directory="/path/to/project"):

428 if session.tag == "needs-review":

429 print(session.summary)

430```

431 

432## Classes

433 

434### `ClaudeSDKClient`

435 

436**Maintains a conversation session across multiple exchanges.** This is the Python equivalent of how the TypeScript SDK's `query()` function works internally - it creates a client object that can continue conversations.

437 

438#### Key Features

439 

440* **Session continuity**: Maintains conversation context across multiple `query()` calls

441* **Same conversation**: The session retains previous messages

442* **Interrupt support**: Can stop execution mid-task

443* **Explicit lifecycle**: You control when the session starts and ends

444* **Response-driven flow**: Can react to responses and send follow-ups

445* **Custom tools and hooks**: Supports custom tools (created with `@tool` decorator) and hooks

446 

447```python theme={null}

448class ClaudeSDKClient:

449 def __init__(self, options: ClaudeAgentOptions | None = None, transport: Transport | None = None)

450 async def connect(self, prompt: str | AsyncIterable[dict] | None = None) -> None

451 async def query(self, prompt: str | AsyncIterable[dict], session_id: str = "default") -> None

452 async def receive_messages(self) -> AsyncIterator[Message]

453 async def receive_response(self) -> AsyncIterator[Message]

454 async def interrupt(self) -> None

455 async def set_permission_mode(self, mode: str) -> None

456 async def set_model(self, model: str | None = None) -> None

457 async def rewind_files(self, user_message_id: str) -> None

458 async def get_mcp_status(self) -> McpStatusResponse

459 async def reconnect_mcp_server(self, server_name: str) -> None

460 async def toggle_mcp_server(self, server_name: str, enabled: bool) -> None

461 async def stop_task(self, task_id: str) -> None

462 async def get_server_info(self) -> dict[str, Any] | None

463 async def disconnect(self) -> None

464```

465 

466#### Methods

467 

468| Method | Description |

469| :---------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- |

470| `__init__(options)` | Initialize the client with optional configuration |

471| `connect(prompt)` | Connect to Claude with an optional initial prompt or message stream |

472| `query(prompt, session_id)` | Send a new request in streaming mode |

473| `receive_messages()` | Receive all messages from Claude as an async iterator |

474| `receive_response()` | Receive messages until and including a ResultMessage |

475| `interrupt()` | Send interrupt signal (only works in streaming mode) |

476| `set_permission_mode(mode)` | Change the permission mode for the current session |

477| `set_model(model)` | Change the model for the current session. Pass `None` to reset to default |

478| `rewind_files(user_message_id)` | Restore files to their state at the specified user message. Requires `enable_file_checkpointing=True`. See [File checkpointing](/en/agent-sdk/file-checkpointing) |

479| `get_mcp_status()` | Get the status of all configured MCP servers. Returns [`McpStatusResponse`](#mcp-status-response) |

480| `reconnect_mcp_server(server_name)` | Retry connecting to an MCP server that failed or was disconnected |

481| `toggle_mcp_server(server_name, enabled)` | Enable or disable an MCP server mid-session. Disabling removes its tools |

482| `stop_task(task_id)` | Stop a running background task. A [`TaskNotificationMessage`](#task-notification-message) with status `"stopped"` follows in the message stream |

483| `get_server_info()` | Get server information including session ID and capabilities |

484| `disconnect()` | Disconnect from Claude |

485 

486#### Context Manager Support

487 

488The client can be used as an async context manager for automatic connection management:

489 

490```python theme={null}

491async with ClaudeSDKClient() as client:

492 await client.query("Hello Claude")

493 async for message in client.receive_response():

494 print(message)

495```

496 

497> **Important:** When iterating over messages, avoid using `break` to exit early as this can cause asyncio cleanup issues. Instead, let the iteration complete naturally or use flags to track when you've found what you need.

498 

499#### Example - Continuing a conversation

500 

501```python theme={null}

502import asyncio

503from claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage

504 

505 

506async def main():

507 async with ClaudeSDKClient() as client:

508 # First question

509 await client.query("What's the capital of France?")

510 

511 # Process response

512 async for message in client.receive_response():

513 if isinstance(message, AssistantMessage):

514 for block in message.content:

515 if isinstance(block, TextBlock):

516 print(f"Claude: {block.text}")

517 

518 # Follow-up question - the session retains the previous context

519 await client.query("What's the population of that city?")

520 

521 async for message in client.receive_response():

522 if isinstance(message, AssistantMessage):

523 for block in message.content:

524 if isinstance(block, TextBlock):

525 print(f"Claude: {block.text}")

526 

527 # Another follow-up - still in the same conversation

528 await client.query("What are some famous landmarks there?")

529 

530 async for message in client.receive_response():

531 if isinstance(message, AssistantMessage):

532 for block in message.content:

533 if isinstance(block, TextBlock):

534 print(f"Claude: {block.text}")

535 

536 

537asyncio.run(main())

538```

539 

540#### Example - Streaming input with ClaudeSDKClient

541 

542```python theme={null}

543import asyncio

544from claude_agent_sdk import ClaudeSDKClient

545 

546 

547async def message_stream():

548 """Generate messages dynamically."""

549 yield {

550 "type": "user",

551 "message": {"role": "user", "content": "Analyze the following data:"},

552 }

553 await asyncio.sleep(0.5)

554 yield {

555 "type": "user",

556 "message": {"role": "user", "content": "Temperature: 25°C, Humidity: 60%"},

557 }

558 await asyncio.sleep(0.5)

559 yield {

560 "type": "user",

561 "message": {"role": "user", "content": "What patterns do you see?"},

562 }

563 

564 

565async def main():

566 async with ClaudeSDKClient() as client:

567 # Stream input to Claude

568 await client.query(message_stream())

569 

570 # Process response

571 async for message in client.receive_response():

572 print(message)

573 

574 # Follow-up in same session

575 await client.query("Should we be concerned about these readings?")

576 

577 async for message in client.receive_response():

578 print(message)

579 

580 

581asyncio.run(main())

582```

583 

584#### Example - Using interrupts

585 

586```python theme={null}

587import asyncio

588from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, ResultMessage

589 

590 

591async def interruptible_task():

592 options = ClaudeAgentOptions(allowed_tools=["Bash"], permission_mode="acceptEdits")

593 

594 async with ClaudeSDKClient(options=options) as client:

595 # Start a long-running task

596 await client.query("Count from 1 to 100 slowly, using the bash sleep command")

597 

598 # Let it run for a bit

599 await asyncio.sleep(2)

600 

601 # Interrupt the task

602 await client.interrupt()

603 print("Task interrupted!")

604 

605 # Drain the interrupted task's messages (including its ResultMessage)

606 async for message in client.receive_response():

607 if isinstance(message, ResultMessage):

608 print(f"Interrupted task finished with subtype={message.subtype!r}")

609 # subtype is "error_during_execution" for interrupted tasks

610 

611 # Send a new command

612 await client.query("Just say hello instead")

613 

614 # Now receive the new response

615 async for message in client.receive_response():

616 if isinstance(message, ResultMessage) and message.subtype == "success":

617 print(f"New result: {message.result}")

618 

619 

620asyncio.run(interruptible_task())

621```

622 

623<Note>

624 **Buffer behavior after interrupt:** `interrupt()` sends a stop signal but does not clear the message buffer. Messages already produced by the interrupted task, including its `ResultMessage` (with `subtype="error_during_execution"`), remain in the stream. You must drain them with `receive_response()` before reading the response to a new query. If you send a new query immediately after `interrupt()` and call `receive_response()` only once, you'll receive the interrupted task's messages, not the new query's response.

625</Note>

626 

627#### Example - Advanced permission control

628 

629```python theme={null}

630from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions

631from claude_agent_sdk.types import (

632 PermissionResultAllow,

633 PermissionResultDeny,

634 ToolPermissionContext,

635)

636 

637 

638async def custom_permission_handler(

639 tool_name: str, input_data: dict, context: ToolPermissionContext

640) -> PermissionResultAllow | PermissionResultDeny:

641 """Custom logic for tool permissions."""

642 

643 # Block writes to system directories

644 if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"):

645 return PermissionResultDeny(

646 message="System directory write not allowed", interrupt=True

647 )

648 

649 # Redirect sensitive file operations

650 if tool_name in ["Write", "Edit"] and "config" in input_data.get("file_path", ""):

651 safe_path = f"./sandbox/{input_data['file_path']}"

652 return PermissionResultAllow(

653 updated_input={**input_data, "file_path": safe_path}

654 )

655 

656 # Allow everything else

657 return PermissionResultAllow(updated_input=input_data)

658 

659 

660async def main():

661 options = ClaudeAgentOptions(

662 can_use_tool=custom_permission_handler, allowed_tools=["Read", "Write", "Edit"]

663 )

664 

665 async with ClaudeSDKClient(options=options) as client:

666 await client.query("Update the system config file")

667 

668 async for message in client.receive_response():

669 # Will use sandbox path instead

670 print(message)

671 

672 

673asyncio.run(main())

674```

675 

676## Types

677 

678<Note>

679 **`@dataclass` vs `TypedDict`:** This SDK uses two kinds of types. Classes decorated with `@dataclass` (such as `ResultMessage`, `AgentDefinition`, `TextBlock`) are object instances at runtime and support attribute access: `msg.result`. Classes defined with `TypedDict` (such as `ThinkingConfigEnabled`, `McpStdioServerConfig`, `SyncHookJSONOutput`) are **plain dicts at runtime** and require key access: `config["budget_tokens"]`, not `config.budget_tokens`. The `ClassName(field=value)` call syntax works for both, but only dataclasses produce objects with attributes.

680</Note>

681 

682### `SdkMcpTool`

683 

684Definition for an SDK MCP tool created with the `@tool` decorator.

685 

686```python theme={null}

687@dataclass

688class SdkMcpTool(Generic[T]):

689 name: str

690 description: str

691 input_schema: type[T] | dict[str, Any]

692 handler: Callable[[T], Awaitable[dict[str, Any]]]

693 annotations: ToolAnnotations | None = None

694```

695 

696| Property | Type | Description |

697| :------------- | :----------------------------------------- | :--------------------------------------------------------------------------------------------------------- |

698| `name` | `str` | Unique identifier for the tool |

699| `description` | `str` | Human-readable description |

700| `input_schema` | `type[T] \| dict[str, Any]` | Schema for input validation |

701| `handler` | `Callable[[T], Awaitable[dict[str, Any]]]` | Async function that handles tool execution |

702| `annotations` | `ToolAnnotations \| None` | Optional MCP tool annotations (e.g., `readOnlyHint`, `destructiveHint`, `openWorldHint`). From `mcp.types` |

703 

704### `Transport`

705 

706Abstract base class for custom transport implementations. Use this to communicate with the Claude process over a custom channel (for example, a remote connection instead of a local subprocess).

707 

708<Warning>

709 This is a low-level internal API. The interface may change in future releases. Custom implementations must be updated to match any interface changes.

710</Warning>

711 

712```python theme={null}

713from abc import ABC, abstractmethod

714from collections.abc import AsyncIterator

715from typing import Any

716 

717 

718class Transport(ABC):

719 @abstractmethod

720 async def connect(self) -> None: ...

721 

722 @abstractmethod

723 async def write(self, data: str) -> None: ...

724 

725 @abstractmethod

726 def read_messages(self) -> AsyncIterator[dict[str, Any]]: ...

727 

728 @abstractmethod

729 async def close(self) -> None: ...

730 

731 @abstractmethod

732 def is_ready(self) -> bool: ...

733 

734 @abstractmethod

735 async def end_input(self) -> None: ...

736```

737 

738| Method | Description |

739| :---------------- | :-------------------------------------------------------------------------- |

740| `connect()` | Connect the transport and prepare for communication |

741| `write(data)` | Write raw data (JSON + newline) to the transport |

742| `read_messages()` | Async iterator that yields parsed JSON messages |

743| `close()` | Close the connection and clean up resources |

744| `is_ready()` | Returns `True` if the transport can send and receive |

745| `end_input()` | Close the input stream (for example, close stdin for subprocess transports) |

746 

747Import: `from claude_agent_sdk import Transport`

748 

749### `ClaudeAgentOptions`

750 

751Configuration dataclass for Claude Code queries.

752 

753```python theme={null}

754@dataclass

755class ClaudeAgentOptions:

756 tools: list[str] | ToolsPreset | None = None

757 allowed_tools: list[str] = field(default_factory=list)

758 system_prompt: str | SystemPromptPreset | None = None

759 mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)

760 permission_mode: PermissionMode | None = None

761 continue_conversation: bool = False

762 resume: str | None = None

763 max_turns: int | None = None

764 max_budget_usd: float | None = None

765 disallowed_tools: list[str] = field(default_factory=list)

766 model: str | None = None

767 fallback_model: str | None = None

768 betas: list[SdkBeta] = field(default_factory=list)

769 output_format: dict[str, Any] | None = None

770 permission_prompt_tool_name: str | None = None

771 cwd: str | Path | None = None

772 cli_path: str | Path | None = None

773 settings: str | None = None

774 add_dirs: list[str | Path] = field(default_factory=list)

775 env: dict[str, str] = field(default_factory=dict)

776 extra_args: dict[str, str | None] = field(default_factory=dict)

777 max_buffer_size: int | None = None

778 debug_stderr: Any = sys.stderr # Deprecated

779 stderr: Callable[[str], None] | None = None

780 can_use_tool: CanUseTool | None = None

781 hooks: dict[HookEvent, list[HookMatcher]] | None = None

782 user: str | None = None

783 include_partial_messages: bool = False

784 fork_session: bool = False

785 agents: dict[str, AgentDefinition] | None = None

786 setting_sources: list[SettingSource] | None = None

787 sandbox: SandboxSettings | None = None

788 plugins: list[SdkPluginConfig] = field(default_factory=list)

789 max_thinking_tokens: int | None = None # Deprecated: use thinking instead

790 thinking: ThinkingConfig | None = None

791 effort: Literal["low", "medium", "high", "max"] | None = None

792 enable_file_checkpointing: bool = False

793 session_store: SessionStore | None = None

794```

795 

796| Property | Type | Default | Description |

797| :---------------------------- | :------------------------------------------------------------------------------------- | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

798| `tools` | `list[str] \| ToolsPreset \| None` | `None` | Tools configuration. Use `{"type": "preset", "preset": "claude_code"}` for Claude Code's default tools |

799| `allowed_tools` | `list[str]` | `[]` | Tools to auto-approve without prompting. This does not restrict Claude to only these tools; unlisted tools fall through to `permission_mode` and `can_use_tool`. Use `disallowed_tools` to block tools. See [Permissions](/en/agent-sdk/permissions#allow-and-deny-rules) |

800| `system_prompt` | `str \| SystemPromptPreset \| None` | `None` | System prompt configuration. Pass a string for custom prompt, or use `{"type": "preset", "preset": "claude_code"}` for Claude Code's system prompt. Add `"append"` to extend the preset |

801| `mcp_servers` | `dict[str, McpServerConfig] \| str \| Path` | `{}` | MCP server configurations or path to config file |

802| `permission_mode` | `PermissionMode \| None` | `None` | Permission mode for tool usage |

803| `continue_conversation` | `bool` | `False` | Continue the most recent conversation |

804| `resume` | `str \| None` | `None` | Session ID to resume |

805| `max_turns` | `int \| None` | `None` | Maximum agentic turns (tool-use round trips) |

806| `max_budget_usd` | `float \| None` | `None` | Stop the query when the client-side cost estimate reaches this USD value. Compared against the same estimate as `total_cost_usd`; see [Track cost and usage](/en/agent-sdk/cost-tracking) for accuracy caveats |

807| `disallowed_tools` | `list[str]` | `[]` | Tools to always deny. Deny rules are checked first and override `allowed_tools` and `permission_mode` (including `bypassPermissions`) |

808| `enable_file_checkpointing` | `bool` | `False` | Enable file change tracking for rewinding. See [File checkpointing](/en/agent-sdk/file-checkpointing) |

809| `model` | `str \| None` | `None` | Claude model to use |

810| `fallback_model` | `str \| None` | `None` | Fallback model to use if the primary model fails |

811| `betas` | `list[SdkBeta]` | `[]` | Beta features to enable. See [`SdkBeta`](#sdk-beta) for available options |

812| `output_format` | `dict[str, Any] \| None` | `None` | Output format for structured responses (e.g., `{"type": "json_schema", "schema": {...}}`). See [Structured outputs](/en/agent-sdk/structured-outputs) for details |

813| `permission_prompt_tool_name` | `str \| None` | `None` | MCP tool name for permission prompts |

814| `cwd` | `str \| Path \| None` | `None` | Current working directory |

815| `cli_path` | `str \| Path \| None` | `None` | Custom path to the Claude Code CLI executable |

816| `settings` | `str \| None` | `None` | Path to settings file |

817| `add_dirs` | `list[str \| Path]` | `[]` | Additional directories Claude can access |

818| `env` | `dict[str, str]` | `{}` | Environment variables merged on top of the inherited process environment. See [Environment variables](/en/env-vars) for variables the underlying CLI reads |

819| `extra_args` | `dict[str, str \| None]` | `{}` | Additional CLI arguments to pass directly to the CLI |

820| `max_buffer_size` | `int \| None` | `None` | Maximum bytes when buffering CLI stdout |

821| `debug_stderr` | `Any` | `sys.stderr` | *Deprecated* - File-like object for debug output. Use `stderr` callback instead |

822| `stderr` | `Callable[[str], None] \| None` | `None` | Callback function for stderr output from CLI |

823| `can_use_tool` | [`CanUseTool`](#can-use-tool) ` \| None` | `None` | Tool permission callback function. See [Permission types](#can-use-tool) for details |

824| `hooks` | `dict[HookEvent, list[HookMatcher]] \| None` | `None` | Hook configurations for intercepting events |

825| `user` | `str \| None` | `None` | User identifier |

826| `include_partial_messages` | `bool` | `False` | Include partial message streaming events. When enabled, [`StreamEvent`](#stream-event) messages are yielded |

827| `fork_session` | `bool` | `False` | When resuming with `resume`, fork to a new session ID instead of continuing the original session |

828| `agents` | `dict[str, AgentDefinition] \| None` | `None` | Programmatically defined subagents |

829| `plugins` | `list[SdkPluginConfig]` | `[]` | Load custom plugins from local paths. See [Plugins](/en/agent-sdk/plugins) for details |

830| `sandbox` | [`SandboxSettings`](#sandbox-settings) ` \| None` | `None` | Configure sandbox behavior programmatically. See [Sandbox settings](#sandbox-settings) for details |

831| `setting_sources` | `list[SettingSource] \| None` | `None` (CLI defaults: all sources) | Control which filesystem settings to load. Pass `[]` to disable user, project, and local settings. Managed policy settings load regardless. See [Use Claude Code features](/en/agent-sdk/claude-code-features#what-settingsources-does-not-control) |

832| `max_thinking_tokens` | `int \| None` | `None` | *Deprecated* - Maximum tokens for thinking blocks. Use `thinking` instead |

833| `thinking` | [`ThinkingConfig`](#thinking-config) ` \| None` | `None` | Controls extended thinking behavior. Takes precedence over `max_thinking_tokens` |

834| `effort` | `Literal["low", "medium", "high", "max"] \| None` | `None` | Effort level for thinking depth |

835| `session_store` | [`SessionStore`](/en/agent-sdk/session-storage#the-session-store-interface) ` \| None` | `None` | Mirror session transcripts to an external backend so any host can resume them. See [Persist sessions to external storage](/en/agent-sdk/session-storage) |

836 

837### `OutputFormat`

838 

839Configuration for structured output validation. Pass this as a `dict` to the `output_format` field on `ClaudeAgentOptions`:

840 

841```python theme={null}

842# Expected dict shape for output_format

843{

844 "type": "json_schema",

845 "schema": {...}, # Your JSON Schema definition

846}

847```

848 

849| Field | Required | Description |

850| :------- | :------- | :------------------------------------------------- |

851| `type` | Yes | Must be `"json_schema"` for JSON Schema validation |

852| `schema` | Yes | JSON Schema definition for output validation |

853 

854### `SystemPromptPreset`

855 

856Configuration for using Claude Code's preset system prompt with optional additions.

857 

858```python theme={null}

859class SystemPromptPreset(TypedDict):

860 type: Literal["preset"]

861 preset: Literal["claude_code"]

862 append: NotRequired[str]

863 exclude_dynamic_sections: NotRequired[bool]

864```

865 

866| Field | Required | Description |

867| :------------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

868| `type` | Yes | Must be `"preset"` to use a preset system prompt |

869| `preset` | Yes | Must be `"claude_code"` to use Claude Code's system prompt |

870| `append` | No | Additional instructions to append to the preset system prompt |

871| `exclude_dynamic_sections` | No | Move per-session context such as working directory, git status, and memory paths from the system prompt into the first user message. Improves prompt-cache reuse across users and machines. See [Modify system prompts](/en/agent-sdk/modifying-system-prompts#improve-prompt-caching-across-users-and-machines) |

872 

873### `SettingSource`

874 

875Controls which filesystem-based configuration sources the SDK loads settings from.

876 

877```python theme={null}

878SettingSource = Literal["user", "project", "local"]

879```

880 

881| Value | Description | Location |

882| :---------- | :------------------------------------------- | :---------------------------- |

883| `"user"` | Global user settings | `~/.claude/settings.json` |

884| `"project"` | Shared project settings (version controlled) | `.claude/settings.json` |

885| `"local"` | Local project settings (gitignored) | `.claude/settings.local.json` |

886 

887#### Default behavior

888 

889When `setting_sources` is omitted or `None`, `query()` loads the same filesystem settings as the Claude Code CLI: user, project, and local. Managed policy settings are loaded in all cases. See [What settingSources does not control](/en/agent-sdk/claude-code-features#what-settingsources-does-not-control) for inputs that are read regardless of this option, and how to disable them.

890 

891#### Why use setting\_sources

892 

893**Disable filesystem settings:**

894 

895```python theme={null}

896# Do not load user, project, or local settings from disk

897from claude_agent_sdk import query, ClaudeAgentOptions

898 

899async for message in query(

900 prompt="Analyze this code",

901 options=ClaudeAgentOptions(

902 setting_sources=[]

903 ),

904):

905 print(message)

906```

907 

908<Note>

909 In Python SDK 0.1.59 and earlier, an empty list was treated the same as omitting the option, so `setting_sources=[]` did not disable filesystem settings. Upgrade to a newer release if you need an empty list to take effect. The TypeScript SDK is not affected.

910</Note>

911 

912**Load all filesystem settings explicitly:**

913 

914```python theme={null}

915from claude_agent_sdk import query, ClaudeAgentOptions

916 

917async for message in query(

918 prompt="Analyze this code",

919 options=ClaudeAgentOptions(

920 setting_sources=["user", "project", "local"]

921 ),

922):

923 print(message)

924```

925 

926**Load only specific setting sources:**

927 

928```python theme={null}

929# Load only project settings, ignore user and local

930async for message in query(

931 prompt="Run CI checks",

932 options=ClaudeAgentOptions(

933 setting_sources=["project"] # Only .claude/settings.json

934 ),

935):

936 print(message)

937```

938 

939**Testing and CI environments:**

940 

941```python theme={null}

942# Ensure consistent behavior in CI by excluding local settings

943async for message in query(

944 prompt="Run tests",

945 options=ClaudeAgentOptions(

946 setting_sources=["project"], # Only team-shared settings

947 permission_mode="bypassPermissions",

948 ),

949):

950 print(message)

951```

952 

953**SDK-only applications:**

954 

955```python theme={null}

956# Define everything programmatically.

957# Pass [] to opt out of filesystem setting sources.

958async for message in query(

959 prompt="Review this PR",

960 options=ClaudeAgentOptions(

961 setting_sources=[],

962 agents={...},

963 mcp_servers={...},

964 allowed_tools=["Read", "Grep", "Glob"],

965 ),

966):

967 print(message)

968```

969 

970**Loading CLAUDE.md project instructions:**

971 

972```python theme={null}

973# Load project settings to include CLAUDE.md files

974async for message in query(

975 prompt="Add a new feature following project conventions",

976 options=ClaudeAgentOptions(

977 system_prompt={

978 "type": "preset",

979 "preset": "claude_code", # Use Claude Code's system prompt

980 },

981 setting_sources=["project"], # Loads CLAUDE.md from project

982 allowed_tools=["Read", "Write", "Edit"],

983 ),

984):

985 print(message)

986```

987 

988#### Settings precedence

989 

990When multiple sources are loaded, settings are merged with this precedence (highest to lowest):

991 

9921. Local settings (`.claude/settings.local.json`)

9932. Project settings (`.claude/settings.json`)

9943. User settings (`~/.claude/settings.json`)

995 

996Programmatic options such as `agents` and `allowed_tools` override user, project, and local filesystem settings. Managed policy settings take precedence over programmatic options.

997 

998### `AgentDefinition`

999 

1000Configuration for a subagent defined programmatically.

1001 

1002```python theme={null}

1003@dataclass

1004class AgentDefinition:

1005 description: str

1006 prompt: str

1007 tools: list[str] | None = None

1008 disallowedTools: list[str] | None = None

1009 model: str | None = None

1010 skills: list[str] | None = None

1011 memory: Literal["user", "project", "local"] | None = None

1012 mcpServers: list[str | dict[str, Any]] | None = None

1013 initialPrompt: str | None = None

1014 maxTurns: int | None = None

1015 background: bool | None = None

1016 effort: Literal["low", "medium", "high", "max"] | int | None = None

1017 permissionMode: PermissionMode | None = None

1018```

1019 

1020| Field | Required | Description |

1021| :---------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |

1022| `description` | Yes | Natural language description of when to use this agent |

1023| `prompt` | Yes | The agent's system prompt |

1024| `tools` | No | Array of allowed tool names. If omitted, inherits all tools |

1025| `disallowedTools` | No | Array of tool names to remove from the agent's tool set |

1026| `model` | No | Model override for this agent. Accepts an alias such as `"sonnet"`, `"opus"`, `"haiku"`, or `"inherit"`, or a full model ID. If omitted, uses the main model |

1027| `skills` | No | List of skill names available to this agent |

1028| `memory` | No | Memory source for this agent: `"user"`, `"project"`, or `"local"` |

1029| `mcpServers` | No | MCP servers available to this agent. Each entry is a server name or an inline `{name: config}` dict |

1030| `initialPrompt` | No | Auto-submitted as the first user turn when this agent runs as the main thread agent |

1031| `maxTurns` | No | Maximum number of agentic turns before the agent stops |

1032| `background` | No | Run this agent as a non-blocking background task when invoked |

1033| `effort` | No | Reasoning effort level for this agent. Accepts a named level or an integer |

1034| `permissionMode` | No | Permission mode for tool execution within this agent. See [`PermissionMode`](#permission-mode) |

1035 

1036<Note>

1037 `AgentDefinition` field names use camelCase, such as `disallowedTools`, `permissionMode`, and `maxTurns`. These names map directly to the wire format shared with the TypeScript SDK. This differs from `ClaudeAgentOptions`, which uses Python snake\_case for the equivalent top-level fields such as `disallowed_tools` and `permission_mode`. Because `AgentDefinition` is a dataclass, passing a snake\_case keyword raises a `TypeError` at construction time.

1038</Note>

1039 

1040### `PermissionMode`

1041 

1042Permission modes for controlling tool execution.

1043 

1044```python theme={null}

1045PermissionMode = Literal[

1046 "default", # Standard permission behavior

1047 "acceptEdits", # Auto-accept file edits

1048 "plan", # Planning mode - no execution

1049 "dontAsk", # Deny anything not pre-approved instead of prompting

1050 "bypassPermissions", # Bypass all permission checks (use with caution)

1051]

1052```

1053 

1054### `CanUseTool`

1055 

1056Type alias for tool permission callback functions.

1057 

1058```python theme={null}

1059CanUseTool = Callable[

1060 [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]

1061]

1062```

1063 

1064The callback receives:

1065 

1066* `tool_name`: Name of the tool being called

1067* `input_data`: The tool's input parameters

1068* `context`: A `ToolPermissionContext` with additional information

1069 

1070Returns a `PermissionResult` (either `PermissionResultAllow` or `PermissionResultDeny`).

1071 

1072### `ToolPermissionContext`

1073 

1074Context information passed to tool permission callbacks.

1075 

1076```python theme={null}

1077@dataclass

1078class ToolPermissionContext:

1079 signal: Any | None = None # Future: abort signal support

1080 suggestions: list[PermissionUpdate] = field(default_factory=list)

1081```

1082 

1083| Field | Type | Description |

1084| :------------ | :----------------------- | :----------------------------------------- |

1085| `signal` | `Any \| None` | Reserved for future abort signal support |

1086| `suggestions` | `list[PermissionUpdate]` | Permission update suggestions from the CLI |

1087 

1088### `PermissionResult`

1089 

1090Union type for permission callback results.

1091 

1092```python theme={null}

1093PermissionResult = PermissionResultAllow | PermissionResultDeny

1094```

1095 

1096### `PermissionResultAllow`

1097 

1098Result indicating the tool call should be allowed.

1099 

1100```python theme={null}

1101@dataclass

1102class PermissionResultAllow:

1103 behavior: Literal["allow"] = "allow"

1104 updated_input: dict[str, Any] | None = None

1105 updated_permissions: list[PermissionUpdate] | None = None

1106```

1107 

1108| Field | Type | Default | Description |

1109| :-------------------- | :------------------------------- | :-------- | :---------------------------------------- |

1110| `behavior` | `Literal["allow"]` | `"allow"` | Must be "allow" |

1111| `updated_input` | `dict[str, Any] \| None` | `None` | Modified input to use instead of original |

1112| `updated_permissions` | `list[PermissionUpdate] \| None` | `None` | Permission updates to apply |

1113 

1114### `PermissionResultDeny`

1115 

1116Result indicating the tool call should be denied.

1117 

1118```python theme={null}

1119@dataclass

1120class PermissionResultDeny:

1121 behavior: Literal["deny"] = "deny"

1122 message: str = ""

1123 interrupt: bool = False

1124```

1125 

1126| Field | Type | Default | Description |

1127| :---------- | :---------------- | :------- | :----------------------------------------- |

1128| `behavior` | `Literal["deny"]` | `"deny"` | Must be "deny" |

1129| `message` | `str` | `""` | Message explaining why the tool was denied |

1130| `interrupt` | `bool` | `False` | Whether to interrupt the current execution |

1131 

1132### `PermissionUpdate`

1133 

1134Configuration for updating permissions programmatically.

1135 

1136```python theme={null}

1137@dataclass

1138class PermissionUpdate:

1139 type: Literal[

1140 "addRules",

1141 "replaceRules",

1142 "removeRules",

1143 "setMode",

1144 "addDirectories",

1145 "removeDirectories",

1146 ]

1147 rules: list[PermissionRuleValue] | None = None

1148 behavior: Literal["allow", "deny", "ask"] | None = None

1149 mode: PermissionMode | None = None

1150 directories: list[str] | None = None

1151 destination: (

1152 Literal["userSettings", "projectSettings", "localSettings", "session"] | None

1153 ) = None

1154```

1155 

1156| Field | Type | Description |

1157| :------------ | :---------------------------------------- | :---------------------------------------------- |

1158| `type` | `Literal[...]` | The type of permission update operation |

1159| `rules` | `list[PermissionRuleValue] \| None` | Rules for add/replace/remove operations |

1160| `behavior` | `Literal["allow", "deny", "ask"] \| None` | Behavior for rule-based operations |

1161| `mode` | `PermissionMode \| None` | Mode for setMode operation |

1162| `directories` | `list[str] \| None` | Directories for add/remove directory operations |

1163| `destination` | `Literal[...] \| None` | Where to apply the permission update |

1164 

1165### `PermissionRuleValue`

1166 

1167A rule to add, replace, or remove in a permission update.

1168 

1169```python theme={null}

1170@dataclass

1171class PermissionRuleValue:

1172 tool_name: str

1173 rule_content: str | None = None

1174```

1175 

1176### `ToolsPreset`

1177 

1178Preset tools configuration for using Claude Code's default tool set.

1179 

1180```python theme={null}

1181class ToolsPreset(TypedDict):

1182 type: Literal["preset"]

1183 preset: Literal["claude_code"]

1184```

1185 

1186### `ThinkingConfig`

1187 

1188Controls extended thinking behavior. A union of three configurations:

1189 

1190```python theme={null}

1191class ThinkingConfigAdaptive(TypedDict):

1192 type: Literal["adaptive"]

1193 

1194 

1195class ThinkingConfigEnabled(TypedDict):

1196 type: Literal["enabled"]

1197 budget_tokens: int

1198 

1199 

1200class ThinkingConfigDisabled(TypedDict):

1201 type: Literal["disabled"]

1202 

1203 

1204ThinkingConfig = ThinkingConfigAdaptive | ThinkingConfigEnabled | ThinkingConfigDisabled

1205```

1206 

1207| Variant | Fields | Description |

1208| :--------- | :---------------------- | :------------------------------------------- |

1209| `adaptive` | `type` | Claude adaptively decides when to think |

1210| `enabled` | `type`, `budget_tokens` | Enable thinking with a specific token budget |

1211| `disabled` | `type` | Disable thinking |

1212 

1213Because these are `TypedDict` classes, they're plain dicts at runtime. Either construct them as dict literals or call the class like a constructor; both produce a `dict`. Access fields with `config["budget_tokens"]`, not `config.budget_tokens`:

1214 

1215```python theme={null}

1216from claude_agent_sdk import ClaudeAgentOptions, ThinkingConfigEnabled

1217 

1218# Option 1: dict literal (recommended, no import needed)

1219options = ClaudeAgentOptions(thinking={"type": "enabled", "budget_tokens": 20000})

1220 

1221# Option 2: constructor-style (returns a plain dict)

1222config = ThinkingConfigEnabled(type="enabled", budget_tokens=20000)

1223print(config["budget_tokens"]) # 20000

1224# config.budget_tokens would raise AttributeError

1225```

1226 

1227### `SdkBeta`

1228 

1229Literal type for SDK beta features.

1230 

1231```python theme={null}

1232SdkBeta = Literal["context-1m-2025-08-07"]

1233```

1234 

1235Use with the `betas` field in `ClaudeAgentOptions` to enable beta features.

1236 

1237<Warning>

1238 The `context-1m-2025-08-07` beta is retired as of April 30, 2026. Passing this header with Claude Sonnet 4.5 or Sonnet 4 has no effect, and requests that exceed the standard 200k-token context window return an error. To use a 1M-token context window, migrate to [Claude Sonnet 4.6, Claude Opus 4.6, or Claude Opus 4.7](https://platform.claude.com/docs/en/about-claude/models/overview), which include 1M context at standard pricing with no beta header required.

1239</Warning>

1240 

1241### `McpSdkServerConfig`

1242 

1243Configuration for SDK MCP servers created with `create_sdk_mcp_server()`.

1244 

1245```python theme={null}

1246class McpSdkServerConfig(TypedDict):

1247 type: Literal["sdk"]

1248 name: str

1249 instance: Any # MCP Server instance

1250```

1251 

1252### `McpServerConfig`

1253 

1254Union type for MCP server configurations.

1255 

1256```python theme={null}

1257McpServerConfig = (

1258 McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig

1259)

1260```

1261 

1262#### `McpStdioServerConfig`

1263 

1264```python theme={null}

1265class McpStdioServerConfig(TypedDict):

1266 type: NotRequired[Literal["stdio"]] # Optional for backwards compatibility

1267 command: str

1268 args: NotRequired[list[str]]

1269 env: NotRequired[dict[str, str]]

1270```

1271 

1272#### `McpSSEServerConfig`

1273 

1274```python theme={null}

1275class McpSSEServerConfig(TypedDict):

1276 type: Literal["sse"]

1277 url: str

1278 headers: NotRequired[dict[str, str]]

1279```

1280 

1281#### `McpHttpServerConfig`

1282 

1283```python theme={null}

1284class McpHttpServerConfig(TypedDict):

1285 type: Literal["http"]

1286 url: str

1287 headers: NotRequired[dict[str, str]]

1288```

1289 

1290### `McpServerStatusConfig`

1291 

1292The configuration of an MCP server as reported by [`get_mcp_status()`](#methods). This is the union of all [`McpServerConfig`](#mcp-server-config) transport variants plus an output-only `claudeai-proxy` variant for servers proxied through claude.ai.

1293 

1294```python theme={null}

1295McpServerStatusConfig = (

1296 McpStdioServerConfig

1297 | McpSSEServerConfig

1298 | McpHttpServerConfig

1299 | McpSdkServerConfigStatus

1300 | McpClaudeAIProxyServerConfig

1301)

1302```

1303 

1304`McpSdkServerConfigStatus` is the serializable form of [`McpSdkServerConfig`](#mcp-sdk-server-config) with only `type` (`"sdk"`) and `name` (`str`) fields; the in-process `instance` is omitted. `McpClaudeAIProxyServerConfig` has `type` (`"claudeai-proxy"`), `url` (`str`), and `id` (`str`) fields.

1305 

1306### `McpStatusResponse`

1307 

1308Response from [`ClaudeSDKClient.get_mcp_status()`](#methods). Wraps the list of server statuses under the `mcpServers` key.

1309 

1310```python theme={null}

1311class McpStatusResponse(TypedDict):

1312 mcpServers: list[McpServerStatus]

1313```

1314 

1315### `McpServerStatus`

1316 

1317Status of a connected MCP server, contained in [`McpStatusResponse`](#mcp-status-response).

1318 

1319```python theme={null}

1320class McpServerStatus(TypedDict):

1321 name: str

1322 status: McpServerConnectionStatus # "connected" | "failed" | "needs-auth" | "pending" | "disabled"

1323 serverInfo: NotRequired[McpServerInfo]

1324 error: NotRequired[str]

1325 config: NotRequired[McpServerStatusConfig]

1326 scope: NotRequired[str]

1327 tools: NotRequired[list[McpToolInfo]]

1328```

1329 

1330| Field | Type | Description |

1331| :----------- | :-------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

1332| `name` | `str` | Server name |

1333| `status` | `str` | One of `"connected"`, `"failed"`, `"needs-auth"`, `"pending"`, or `"disabled"` |

1334| `serverInfo` | `dict` (optional) | Server name and version (`{"name": str, "version": str}`) |

1335| `error` | `str` (optional) | Error message if the server failed to connect |

1336| `config` | [`McpServerStatusConfig`](#mcp-server-status-config) (optional) | Server configuration. Same shape as [`McpServerConfig`](#mcp-server-config) (stdio, SSE, HTTP, or SDK), plus a `claudeai-proxy` variant for servers connected through claude.ai |

1337| `scope` | `str` (optional) | Configuration scope |

1338| `tools` | `list` (optional) | Tools provided by this server, each with `name`, `description`, and `annotations` fields |

1339 

1340### `SdkPluginConfig`

1341 

1342Configuration for loading plugins in the SDK.

1343 

1344```python theme={null}

1345class SdkPluginConfig(TypedDict):

1346 type: Literal["local"]

1347 path: str

1348```

1349 

1350| Field | Type | Description |

1351| :----- | :----------------- | :--------------------------------------------------------- |

1352| `type` | `Literal["local"]` | Must be `"local"` (only local plugins currently supported) |

1353| `path` | `str` | Absolute or relative path to the plugin directory |

1354 

1355**Example:**

1356 

1357```python theme={null}

1358plugins = [

1359 {"type": "local", "path": "./my-plugin"},

1360 {"type": "local", "path": "/absolute/path/to/plugin"},

1361]

1362```

1363 

1364For complete information on creating and using plugins, see [Plugins](/en/agent-sdk/plugins).

1365 

1366## Message Types

1367 

1368### `Message`

1369 

1370Union type of all possible messages.

1371 

1372```python theme={null}

1373Message = (

1374 UserMessage

1375 | AssistantMessage

1376 | SystemMessage

1377 | ResultMessage

1378 | StreamEvent

1379 | RateLimitEvent

1380)

1381```

1382 

1383### `UserMessage`

1384 

1385User input message.

1386 

1387```python theme={null}

1388@dataclass

1389class UserMessage:

1390 content: str | list[ContentBlock]

1391 uuid: str | None = None

1392 parent_tool_use_id: str | None = None

1393 tool_use_result: dict[str, Any] | None = None

1394```

1395 

1396| Field | Type | Description |

1397| :------------------- | :-------------------------- | :---------------------------------------------------- |

1398| `content` | `str \| list[ContentBlock]` | Message content as text or content blocks |

1399| `uuid` | `str \| None` | Unique message identifier |

1400| `parent_tool_use_id` | `str \| None` | Tool use ID if this message is a tool result response |

1401| `tool_use_result` | `dict[str, Any] \| None` | Tool result data if applicable |

1402 

1403### `AssistantMessage`

1404 

1405Assistant response message with content blocks.

1406 

1407```python theme={null}

1408@dataclass

1409class AssistantMessage:

1410 content: list[ContentBlock]

1411 model: str

1412 parent_tool_use_id: str | None = None

1413 error: AssistantMessageError | None = None

1414 usage: dict[str, Any] | None = None

1415 message_id: str | None = None

1416```

1417 

1418| Field | Type | Description |

1419| :------------------- | :------------------------------------------------------------- | :------------------------------------------------------------------------------ |

1420| `content` | `list[ContentBlock]` | List of content blocks in the response |

1421| `model` | `str` | Model that generated the response |

1422| `parent_tool_use_id` | `str \| None` | Tool use ID if this is a nested response |

1423| `error` | [`AssistantMessageError`](#assistant-message-error) ` \| None` | Error type if the response encountered an error |

1424| `usage` | `dict[str, Any] \| None` | Per-message token usage (same keys as [`ResultMessage.usage`](#result-message)) |

1425| `message_id` | `str \| None` | API message ID. Multiple messages from one turn share the same ID |

1426 

1427### `AssistantMessageError`

1428 

1429Possible error types for assistant messages.

1430 

1431```python theme={null}

1432AssistantMessageError = Literal[

1433 "authentication_failed",

1434 "billing_error",

1435 "rate_limit",

1436 "invalid_request",

1437 "server_error",

1438 "max_output_tokens",

1439 "unknown",

1440]

1441```

1442 

1443### `SystemMessage`

1444 

1445System message with metadata.

1446 

1447```python theme={null}

1448@dataclass

1449class SystemMessage:

1450 subtype: str

1451 data: dict[str, Any]

1452```

1453 

1454### `ResultMessage`

1455 

1456Final result message with cost and usage information.

1457 

1458```python theme={null}

1459@dataclass

1460class ResultMessage:

1461 subtype: str

1462 duration_ms: int

1463 duration_api_ms: int

1464 is_error: bool

1465 num_turns: int

1466 session_id: str

1467 total_cost_usd: float | None = None

1468 usage: dict[str, Any] | None = None

1469 result: str | None = None

1470 stop_reason: str | None = None

1471 structured_output: Any = None

1472 model_usage: dict[str, Any] | None = None

1473```

1474 

1475The `usage` dict contains the following keys when present:

1476 

1477| Key | Type | Description |

1478| ----------------------------- | ----- | ---------------------------------------- |

1479| `input_tokens` | `int` | Total input tokens consumed. |

1480| `output_tokens` | `int` | Total output tokens generated. |

1481| `cache_creation_input_tokens` | `int` | Tokens used to create new cache entries. |

1482| `cache_read_input_tokens` | `int` | Tokens read from existing cache entries. |

1483 

1484The `model_usage` dict maps model names to per-model usage. The inner dict keys use camelCase because the value is passed through unmodified from the underlying CLI process, matching the TypeScript [`ModelUsage`](/en/agent-sdk/typescript#model-usage) type:

1485 

1486| Key | Type | Description |

1487| -------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------- |

1488| `inputTokens` | `int` | Input tokens for this model. |

1489| `outputTokens` | `int` | Output tokens for this model. |

1490| `cacheReadInputTokens` | `int` | Cache read tokens for this model. |

1491| `cacheCreationInputTokens` | `int` | Cache creation tokens for this model. |

1492| `webSearchRequests` | `int` | Web search requests made by this model. |

1493| `costUSD` | `float` | Estimated cost in USD for this model, computed client-side. See [Track cost and usage](/en/agent-sdk/cost-tracking) for billing caveats. |

1494| `contextWindow` | `int` | Context window size for this model. |

1495| `maxOutputTokens` | `int` | Maximum output token limit for this model. |

1496 

1497### `StreamEvent`

1498 

1499Stream event for partial message updates during streaming. Only received when `include_partial_messages=True` in `ClaudeAgentOptions`. Import via `from claude_agent_sdk.types import StreamEvent`.

1500 

1501```python theme={null}

1502@dataclass

1503class StreamEvent:

1504 uuid: str

1505 session_id: str

1506 event: dict[str, Any] # The raw Claude API stream event

1507 parent_tool_use_id: str | None = None

1508```

1509 

1510| Field | Type | Description |

1511| :------------------- | :--------------- | :-------------------------------------------------- |

1512| `uuid` | `str` | Unique identifier for this event |

1513| `session_id` | `str` | Session identifier |

1514| `event` | `dict[str, Any]` | The raw Claude API stream event data |

1515| `parent_tool_use_id` | `str \| None` | Parent tool use ID if this event is from a subagent |

1516 

1517### `RateLimitEvent`

1518 

1519Emitted when rate limit status changes (for example, from `"allowed"` to `"allowed_warning"`). Use this to warn users before they hit a hard limit, or to back off when status is `"rejected"`.

1520 

1521```python theme={null}

1522@dataclass

1523class RateLimitEvent:

1524 rate_limit_info: RateLimitInfo

1525 uuid: str

1526 session_id: str

1527```

1528 

1529| Field | Type | Description |

1530| :---------------- | :---------------------------------- | :----------------------- |

1531| `rate_limit_info` | [`RateLimitInfo`](#rate-limit-info) | Current rate limit state |

1532| `uuid` | `str` | Unique event identifier |

1533| `session_id` | `str` | Session identifier |

1534 

1535### `RateLimitInfo`

1536 

1537Rate limit state carried by [`RateLimitEvent`](#rate-limit-event).

1538 

1539```python theme={null}

1540RateLimitStatus = Literal["allowed", "allowed_warning", "rejected"]

1541RateLimitType = Literal[

1542 "five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet", "overage"

1543]

1544 

1545 

1546@dataclass

1547class RateLimitInfo:

1548 status: RateLimitStatus

1549 resets_at: int | None = None

1550 rate_limit_type: RateLimitType | None = None

1551 utilization: float | None = None

1552 overage_status: RateLimitStatus | None = None

1553 overage_resets_at: int | None = None

1554 overage_disabled_reason: str | None = None

1555 raw: dict[str, Any] = field(default_factory=dict)

1556```

1557 

1558| Field | Type | Description |

1559| :------------------------ | :------------------------ | :---------------------------------------------------------------------------------------------------- |

1560| `status` | `RateLimitStatus` | Current status. `"allowed_warning"` means approaching the limit; `"rejected"` means the limit was hit |

1561| `resets_at` | `int \| None` | Unix timestamp when the rate limit window resets |

1562| `rate_limit_type` | `RateLimitType \| None` | Which rate limit window applies |

1563| `utilization` | `float \| None` | Fraction of the rate limit consumed (0.0 to 1.0) |

1564| `overage_status` | `RateLimitStatus \| None` | Status of pay-as-you-go overage usage, if applicable |

1565| `overage_resets_at` | `int \| None` | Unix timestamp when the overage window resets |

1566| `overage_disabled_reason` | `str \| None` | Why overage is unavailable, if status is `"rejected"` |

1567| `raw` | `dict[str, Any]` | Full raw dict from the CLI, including fields not modeled above |

1568 

1569### `TaskStartedMessage`

1570 

1571Emitted when a background task starts. A background task is anything tracked outside the main turn: a backgrounded Bash command, a [Monitor](#monitor) watch, a subagent spawned via the Agent tool, or a remote agent. The `task_type` field tells you which. This naming is unrelated to the `Task`-to-`Agent` tool rename.

1572 

1573```python theme={null}

1574@dataclass

1575class TaskStartedMessage(SystemMessage):

1576 task_id: str

1577 description: str

1578 uuid: str

1579 session_id: str

1580 tool_use_id: str | None = None

1581 task_type: str | None = None

1582```

1583 

1584| Field | Type | Description |

1585| :------------ | :------------ | :-------------------------------------------------------------------------------------------------------------------------- |

1586| `task_id` | `str` | Unique identifier for the task |

1587| `description` | `str` | Description of the task |

1588| `uuid` | `str` | Unique message identifier |

1589| `session_id` | `str` | Session identifier |

1590| `tool_use_id` | `str \| None` | Associated tool use ID |

1591| `task_type` | `str \| None` | Which kind of background task: `"local_bash"` for background Bash and Monitor watches, `"local_agent"`, or `"remote_agent"` |

1592 

1593### `TaskUsage`

1594 

1595Token and timing data for a background task.

1596 

1597```python theme={null}

1598class TaskUsage(TypedDict):

1599 total_tokens: int

1600 tool_uses: int

1601 duration_ms: int

1602```

1603 

1604### `TaskProgressMessage`

1605 

1606Emitted periodically with progress updates for a running background task.

1607 

1608```python theme={null}

1609@dataclass

1610class TaskProgressMessage(SystemMessage):

1611 task_id: str

1612 description: str

1613 usage: TaskUsage

1614 uuid: str

1615 session_id: str

1616 tool_use_id: str | None = None

1617 last_tool_name: str | None = None

1618```

1619 

1620| Field | Type | Description |

1621| :--------------- | :------------ | :---------------------------------- |

1622| `task_id` | `str` | Unique identifier for the task |

1623| `description` | `str` | Current status description |

1624| `usage` | `TaskUsage` | Token usage for this task so far |

1625| `uuid` | `str` | Unique message identifier |

1626| `session_id` | `str` | Session identifier |

1627| `tool_use_id` | `str \| None` | Associated tool use ID |

1628| `last_tool_name` | `str \| None` | Name of the last tool the task used |

1629 

1630### `TaskNotificationMessage`

1631 

1632Emitted when a background task completes, fails, or is stopped. Background tasks include `run_in_background` Bash commands, Monitor watches, and background subagents.

1633 

1634```python theme={null}

1635@dataclass

1636class TaskNotificationMessage(SystemMessage):

1637 task_id: str

1638 status: TaskNotificationStatus # "completed" | "failed" | "stopped"

1639 output_file: str

1640 summary: str

1641 uuid: str

1642 session_id: str

1643 tool_use_id: str | None = None

1644 usage: TaskUsage | None = None

1645```

1646 

1647| Field | Type | Description |

1648| :------------ | :----------------------- | :----------------------------------------------- |

1649| `task_id` | `str` | Unique identifier for the task |

1650| `status` | `TaskNotificationStatus` | One of `"completed"`, `"failed"`, or `"stopped"` |

1651| `output_file` | `str` | Path to the task output file |

1652| `summary` | `str` | Summary of the task result |

1653| `uuid` | `str` | Unique message identifier |

1654| `session_id` | `str` | Session identifier |

1655| `tool_use_id` | `str \| None` | Associated tool use ID |

1656| `usage` | `TaskUsage \| None` | Final token usage for the task |

1657 

1658## Content Block Types

1659 

1660### `ContentBlock`

1661 

1662Union type of all content blocks.

1663 

1664```python theme={null}

1665ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock

1666```

1667 

1668### `TextBlock`

1669 

1670Text content block.

1671 

1672```python theme={null}

1673@dataclass

1674class TextBlock:

1675 text: str

1676```

1677 

1678### `ThinkingBlock`

1679 

1680Thinking content block (for models with thinking capability).

1681 

1682```python theme={null}

1683@dataclass

1684class ThinkingBlock:

1685 thinking: str

1686 signature: str

1687```

1688 

1689### `ToolUseBlock`

1690 

1691Tool use request block.

1692 

1693```python theme={null}

1694@dataclass

1695class ToolUseBlock:

1696 id: str

1697 name: str

1698 input: dict[str, Any]

1699```

1700 

1701### `ToolResultBlock`

1702 

1703Tool execution result block.

1704 

1705```python theme={null}

1706@dataclass

1707class ToolResultBlock:

1708 tool_use_id: str

1709 content: str | list[dict[str, Any]] | None = None

1710 is_error: bool | None = None

1711```

1712 

1713## Error Types

1714 

1715### `ClaudeSDKError`

1716 

1717Base exception class for all SDK errors.

1718 

1719```python theme={null}

1720class ClaudeSDKError(Exception):

1721 """Base error for Claude SDK."""

1722```

1723 

1724### `CLINotFoundError`

1725 

1726Raised when Claude Code CLI is not installed or not found.

1727 

1728```python theme={null}

1729class CLINotFoundError(CLIConnectionError):

1730 def __init__(

1731 self, message: str = "Claude Code not found", cli_path: str | None = None

1732 ):

1733 """

1734 Args:

1735 message: Error message (default: "Claude Code not found")

1736 cli_path: Optional path to the CLI that was not found

1737 """

1738```

1739 

1740### `CLIConnectionError`

1741 

1742Raised when connection to Claude Code fails.

1743 

1744```python theme={null}

1745class CLIConnectionError(ClaudeSDKError):

1746 """Failed to connect to Claude Code."""

1747```

1748 

1749### `ProcessError`

1750 

1751Raised when the Claude Code process fails.

1752 

1753```python theme={null}

1754class ProcessError(ClaudeSDKError):

1755 def __init__(

1756 self, message: str, exit_code: int | None = None, stderr: str | None = None

1757 ):

1758 self.exit_code = exit_code

1759 self.stderr = stderr

1760```

1761 

1762### `CLIJSONDecodeError`

1763 

1764Raised when JSON parsing fails.

1765 

1766```python theme={null}

1767class CLIJSONDecodeError(ClaudeSDKError):

1768 def __init__(self, line: str, original_error: Exception):

1769 """

1770 Args:

1771 line: The line that failed to parse

1772 original_error: The original JSON decode exception

1773 """

1774 self.line = line

1775 self.original_error = original_error

1776```

1777 

1778## Hook Types

1779 

1780For a comprehensive guide on using hooks with examples and common patterns, see the [Hooks guide](/en/agent-sdk/hooks).

1781 

1782### `HookEvent`

1783 

1784Supported hook event types.

1785 

1786```python theme={null}

1787HookEvent = Literal[

1788 "PreToolUse", # Called before tool execution

1789 "PostToolUse", # Called after tool execution

1790 "PostToolUseFailure", # Called when a tool execution fails

1791 "UserPromptSubmit", # Called when user submits a prompt

1792 "Stop", # Called when stopping execution

1793 "SubagentStop", # Called when a subagent stops

1794 "PreCompact", # Called before message compaction

1795 "Notification", # Called for notification events

1796 "SubagentStart", # Called when a subagent starts

1797 "PermissionRequest", # Called when a permission decision is needed

1798]

1799```

1800 

1801<Note>

1802 The TypeScript SDK supports additional hook events not yet available in Python: `SessionStart`, `SessionEnd`, `Setup`, `TeammateIdle`, `TaskCompleted`, `ConfigChange`, `WorktreeCreate`, `WorktreeRemove`, and `PostToolBatch`.

1803</Note>

1804 

1805### `HookCallback`

1806 

1807Type definition for hook callback functions.

1808 

1809```python theme={null}

1810HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]

1811```

1812 

1813Parameters:

1814 

1815* `input`: Strongly-typed hook input with discriminated unions based on `hook_event_name` (see [`HookInput`](#hook-input))

1816* `tool_use_id`: Optional tool use identifier (for tool-related hooks)

1817* `context`: Hook context with additional information

1818 

1819Returns a [`HookJSONOutput`](#hook-json-output) that may contain:

1820 

1821* `decision`: `"block"` to block the action

1822* `systemMessage`: System message to add to the transcript

1823* `hookSpecificOutput`: Hook-specific output data

1824 

1825### `HookContext`

1826 

1827Context information passed to hook callbacks.

1828 

1829```python theme={null}

1830class HookContext(TypedDict):

1831 signal: Any | None # Future: abort signal support

1832```

1833 

1834### `HookMatcher`

1835 

1836Configuration for matching hooks to specific events or tools.

1837 

1838```python theme={null}

1839@dataclass

1840class HookMatcher:

1841 matcher: str | None = (

1842 None # Tool name or pattern to match (e.g., "Bash", "Write|Edit")

1843 )

1844 hooks: list[HookCallback] = field(

1845 default_factory=list

1846 ) # List of callbacks to execute

1847 timeout: float | None = (

1848 None # Timeout in seconds for all hooks in this matcher (default: 60)

1849 )

1850```

1851 

1852### `HookInput`

1853 

1854Union type of all hook input types. The actual type depends on the `hook_event_name` field.

1855 

1856```python theme={null}

1857HookInput = (

1858 PreToolUseHookInput

1859 | PostToolUseHookInput

1860 | PostToolUseFailureHookInput

1861 | UserPromptSubmitHookInput

1862 | StopHookInput

1863 | SubagentStopHookInput

1864 | PreCompactHookInput

1865 | NotificationHookInput

1866 | SubagentStartHookInput

1867 | PermissionRequestHookInput

1868)

1869```

1870 

1871### `BaseHookInput`

1872 

1873Base fields present in all hook input types.

1874 

1875```python theme={null}

1876class BaseHookInput(TypedDict):

1877 session_id: str

1878 transcript_path: str

1879 cwd: str

1880 permission_mode: NotRequired[str]

1881```

1882 

1883| Field | Type | Description |

1884| :---------------- | :--------------- | :---------------------------------- |

1885| `session_id` | `str` | Current session identifier |

1886| `transcript_path` | `str` | Path to the session transcript file |

1887| `cwd` | `str` | Current working directory |

1888| `permission_mode` | `str` (optional) | Current permission mode |

1889 

1890### `PreToolUseHookInput`

1891 

1892Input data for `PreToolUse` hook events.

1893 

1894```python theme={null}

1895class PreToolUseHookInput(BaseHookInput):

1896 hook_event_name: Literal["PreToolUse"]

1897 tool_name: str

1898 tool_input: dict[str, Any]

1899 tool_use_id: str

1900 agent_id: NotRequired[str]

1901 agent_type: NotRequired[str]

1902```

1903 

1904| Field | Type | Description |

1905| :---------------- | :---------------------- | :----------------------------------------------------------------- |

1906| `hook_event_name` | `Literal["PreToolUse"]` | Always "PreToolUse" |

1907| `tool_name` | `str` | Name of the tool about to be executed |

1908| `tool_input` | `dict[str, Any]` | Input parameters for the tool |

1909| `tool_use_id` | `str` | Unique identifier for this tool use |

1910| `agent_id` | `str` (optional) | Subagent identifier, present when the hook fires inside a subagent |

1911| `agent_type` | `str` (optional) | Subagent type, present when the hook fires inside a subagent |

1912 

1913### `PostToolUseHookInput`

1914 

1915Input data for `PostToolUse` hook events.

1916 

1917```python theme={null}

1918class PostToolUseHookInput(BaseHookInput):

1919 hook_event_name: Literal["PostToolUse"]

1920 tool_name: str

1921 tool_input: dict[str, Any]

1922 tool_response: Any

1923 tool_use_id: str

1924 agent_id: NotRequired[str]

1925 agent_type: NotRequired[str]

1926```

1927 

1928| Field | Type | Description |

1929| :---------------- | :----------------------- | :----------------------------------------------------------------- |

1930| `hook_event_name` | `Literal["PostToolUse"]` | Always "PostToolUse" |

1931| `tool_name` | `str` | Name of the tool that was executed |

1932| `tool_input` | `dict[str, Any]` | Input parameters that were used |

1933| `tool_response` | `Any` | Response from the tool execution |

1934| `tool_use_id` | `str` | Unique identifier for this tool use |

1935| `agent_id` | `str` (optional) | Subagent identifier, present when the hook fires inside a subagent |

1936| `agent_type` | `str` (optional) | Subagent type, present when the hook fires inside a subagent |

1937 

1938### `PostToolUseFailureHookInput`

1939 

1940Input data for `PostToolUseFailure` hook events. Called when a tool execution fails.

1941 

1942```python theme={null}

1943class PostToolUseFailureHookInput(BaseHookInput):

1944 hook_event_name: Literal["PostToolUseFailure"]

1945 tool_name: str

1946 tool_input: dict[str, Any]

1947 tool_use_id: str

1948 error: str

1949 is_interrupt: NotRequired[bool]

1950 agent_id: NotRequired[str]

1951 agent_type: NotRequired[str]

1952```

1953 

1954| Field | Type | Description |

1955| :---------------- | :------------------------------ | :----------------------------------------------------------------- |

1956| `hook_event_name` | `Literal["PostToolUseFailure"]` | Always "PostToolUseFailure" |

1957| `tool_name` | `str` | Name of the tool that failed |

1958| `tool_input` | `dict[str, Any]` | Input parameters that were used |

1959| `tool_use_id` | `str` | Unique identifier for this tool use |

1960| `error` | `str` | Error message from the failed execution |

1961| `is_interrupt` | `bool` (optional) | Whether the failure was caused by an interrupt |

1962| `agent_id` | `str` (optional) | Subagent identifier, present when the hook fires inside a subagent |

1963| `agent_type` | `str` (optional) | Subagent type, present when the hook fires inside a subagent |

1964 

1965### `UserPromptSubmitHookInput`

1966 

1967Input data for `UserPromptSubmit` hook events.

1968 

1969```python theme={null}

1970class UserPromptSubmitHookInput(BaseHookInput):

1971 hook_event_name: Literal["UserPromptSubmit"]

1972 prompt: str

1973```

1974 

1975| Field | Type | Description |

1976| :---------------- | :---------------------------- | :-------------------------- |

1977| `hook_event_name` | `Literal["UserPromptSubmit"]` | Always "UserPromptSubmit" |

1978| `prompt` | `str` | The user's submitted prompt |

1979 

1980### `StopHookInput`

1981 

1982Input data for `Stop` hook events.

1983 

1984```python theme={null}

1985class StopHookInput(BaseHookInput):

1986 hook_event_name: Literal["Stop"]

1987 stop_hook_active: bool

1988```

1989 

1990| Field | Type | Description |

1991| :----------------- | :---------------- | :------------------------------ |

1992| `hook_event_name` | `Literal["Stop"]` | Always "Stop" |

1993| `stop_hook_active` | `bool` | Whether the stop hook is active |

1994 

1995### `SubagentStopHookInput`

1996 

1997Input data for `SubagentStop` hook events.

1998 

1999```python theme={null}

2000class SubagentStopHookInput(BaseHookInput):

2001 hook_event_name: Literal["SubagentStop"]

2002 stop_hook_active: bool

2003 agent_id: str

2004 agent_transcript_path: str

2005 agent_type: str

2006```

2007 

2008| Field | Type | Description |

2009| :---------------------- | :------------------------ | :------------------------------------- |

2010| `hook_event_name` | `Literal["SubagentStop"]` | Always "SubagentStop" |

2011| `stop_hook_active` | `bool` | Whether the stop hook is active |

2012| `agent_id` | `str` | Unique identifier for the subagent |

2013| `agent_transcript_path` | `str` | Path to the subagent's transcript file |

2014| `agent_type` | `str` | Type of the subagent |

2015 

2016### `PreCompactHookInput`

2017 

2018Input data for `PreCompact` hook events.

2019 

2020```python theme={null}

2021class PreCompactHookInput(BaseHookInput):

2022 hook_event_name: Literal["PreCompact"]

2023 trigger: Literal["manual", "auto"]

2024 custom_instructions: str | None

2025```

2026 

2027| Field | Type | Description |

2028| :-------------------- | :-------------------------- | :--------------------------------- |

2029| `hook_event_name` | `Literal["PreCompact"]` | Always "PreCompact" |

2030| `trigger` | `Literal["manual", "auto"]` | What triggered the compaction |

2031| `custom_instructions` | `str \| None` | Custom instructions for compaction |

2032 

2033### `NotificationHookInput`

2034 

2035Input data for `Notification` hook events.

2036 

2037```python theme={null}

2038class NotificationHookInput(BaseHookInput):

2039 hook_event_name: Literal["Notification"]

2040 message: str

2041 title: NotRequired[str]

2042 notification_type: str

2043```

2044 

2045| Field | Type | Description |

2046| :------------------ | :------------------------ | :--------------------------- |

2047| `hook_event_name` | `Literal["Notification"]` | Always "Notification" |

2048| `message` | `str` | Notification message content |

2049| `title` | `str` (optional) | Notification title |

2050| `notification_type` | `str` | Type of notification |

2051 

2052### `SubagentStartHookInput`

2053 

2054Input data for `SubagentStart` hook events.

2055 

2056```python theme={null}

2057class SubagentStartHookInput(BaseHookInput):

2058 hook_event_name: Literal["SubagentStart"]

2059 agent_id: str

2060 agent_type: str

2061```

2062 

2063| Field | Type | Description |

2064| :---------------- | :------------------------- | :--------------------------------- |

2065| `hook_event_name` | `Literal["SubagentStart"]` | Always "SubagentStart" |

2066| `agent_id` | `str` | Unique identifier for the subagent |

2067| `agent_type` | `str` | Type of the subagent |

2068 

2069### `PermissionRequestHookInput`

2070 

2071Input data for `PermissionRequest` hook events. Allows hooks to handle permission decisions programmatically.

2072 

2073```python theme={null}

2074class PermissionRequestHookInput(BaseHookInput):

2075 hook_event_name: Literal["PermissionRequest"]

2076 tool_name: str

2077 tool_input: dict[str, Any]

2078 permission_suggestions: NotRequired[list[Any]]

2079```

2080 

2081| Field | Type | Description |

2082| :----------------------- | :----------------------------- | :---------------------------------------- |

2083| `hook_event_name` | `Literal["PermissionRequest"]` | Always "PermissionRequest" |

2084| `tool_name` | `str` | Name of the tool requesting permission |

2085| `tool_input` | `dict[str, Any]` | Input parameters for the tool |

2086| `permission_suggestions` | `list[Any]` (optional) | Suggested permission updates from the CLI |

2087 

2088### `HookJSONOutput`

2089 

2090Union type for hook callback return values.

2091 

2092```python theme={null}

2093HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput

2094```

2095 

2096#### `SyncHookJSONOutput`

2097 

2098Synchronous hook output with control and decision fields.

2099 

2100```python theme={null}

2101class SyncHookJSONOutput(TypedDict):

2102 # Control fields

2103 continue_: NotRequired[bool] # Whether to proceed (default: True)

2104 suppressOutput: NotRequired[bool] # Hide stdout from transcript

2105 stopReason: NotRequired[str] # Message when continue is False

2106 

2107 # Decision fields

2108 decision: NotRequired[Literal["block"]]

2109 systemMessage: NotRequired[str] # Warning message for user

2110 reason: NotRequired[str] # Feedback for Claude

2111 

2112 # Hook-specific output

2113 hookSpecificOutput: NotRequired[HookSpecificOutput]

2114```

2115 

2116<Note>

2117 Use `continue_` (with underscore) in Python code. It is automatically converted to `continue` when sent to the CLI.

2118</Note>

2119 

2120#### `HookSpecificOutput`

2121 

2122A `TypedDict` containing the hook event name and event-specific fields. The shape depends on the `hookEventName` value. For full details on available fields per hook event, see [Control execution with hooks](/en/agent-sdk/hooks#outputs).

2123 

2124A discriminated union of event-specific output types. The `hookEventName` field determines which fields are valid.

2125 

2126```python theme={null}

2127class PreToolUseHookSpecificOutput(TypedDict):

2128 hookEventName: Literal["PreToolUse"]

2129 permissionDecision: NotRequired[Literal["allow", "deny", "ask"]]

2130 permissionDecisionReason: NotRequired[str]

2131 updatedInput: NotRequired[dict[str, Any]]

2132 additionalContext: NotRequired[str]

2133 

2134 

2135class PostToolUseHookSpecificOutput(TypedDict):

2136 hookEventName: Literal["PostToolUse"]

2137 additionalContext: NotRequired[str]

2138 updatedMCPToolOutput: NotRequired[Any]

2139 

2140 

2141class PostToolUseFailureHookSpecificOutput(TypedDict):

2142 hookEventName: Literal["PostToolUseFailure"]

2143 additionalContext: NotRequired[str]

2144 

2145 

2146class UserPromptSubmitHookSpecificOutput(TypedDict):

2147 hookEventName: Literal["UserPromptSubmit"]

2148 additionalContext: NotRequired[str]

2149 

2150 

2151class NotificationHookSpecificOutput(TypedDict):

2152 hookEventName: Literal["Notification"]

2153 additionalContext: NotRequired[str]

2154 

2155 

2156class SubagentStartHookSpecificOutput(TypedDict):

2157 hookEventName: Literal["SubagentStart"]

2158 additionalContext: NotRequired[str]

2159 

2160 

2161class PermissionRequestHookSpecificOutput(TypedDict):

2162 hookEventName: Literal["PermissionRequest"]

2163 decision: dict[str, Any]

2164 

2165 

2166HookSpecificOutput = (

2167 PreToolUseHookSpecificOutput

2168 | PostToolUseHookSpecificOutput

2169 | PostToolUseFailureHookSpecificOutput

2170 | UserPromptSubmitHookSpecificOutput

2171 | NotificationHookSpecificOutput

2172 | SubagentStartHookSpecificOutput

2173 | PermissionRequestHookSpecificOutput

2174)

2175```

2176 

2177#### `AsyncHookJSONOutput`

2178 

2179Async hook output that defers hook execution.

2180 

2181```python theme={null}

2182class AsyncHookJSONOutput(TypedDict):

2183 async_: Literal[True] # Set to True to defer execution

2184 asyncTimeout: NotRequired[int] # Timeout in milliseconds

2185```

2186 

2187<Note>

2188 Use `async_` (with underscore) in Python code. It is automatically converted to `async` when sent to the CLI.

2189</Note>

2190 

2191### Hook Usage Example

2192 

2193This example registers two hooks: one that blocks dangerous bash commands like `rm -rf /`, and another that logs all tool usage for auditing. The security hook only runs on Bash commands (via the `matcher`), while the logging hook runs on all tools.

2194 

2195```python theme={null}

2196from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContext

2197from typing import Any

2198 

2199 

2200async def validate_bash_command(

2201 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext

2202) -> dict[str, Any]:

2203 """Validate and potentially block dangerous bash commands."""

2204 if input_data["tool_name"] == "Bash":

2205 command = input_data["tool_input"].get("command", "")

2206 if "rm -rf /" in command:

2207 return {

2208 "hookSpecificOutput": {

2209 "hookEventName": "PreToolUse",

2210 "permissionDecision": "deny",

2211 "permissionDecisionReason": "Dangerous command blocked",

2212 }

2213 }

2214 return {}

2215 

2216 

2217async def log_tool_use(

2218 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext

2219) -> dict[str, Any]:

2220 """Log all tool usage for auditing."""

2221 print(f"Tool used: {input_data.get('tool_name')}")

2222 return {}

2223 

2224 

2225options = ClaudeAgentOptions(

2226 hooks={

2227 "PreToolUse": [

2228 HookMatcher(

2229 matcher="Bash", hooks=[validate_bash_command], timeout=120

2230 ), # 2 min for validation

2231 HookMatcher(

2232 hooks=[log_tool_use]

2233 ), # Applies to all tools (default 60s timeout)

2234 ],

2235 "PostToolUse": [HookMatcher(hooks=[log_tool_use])],

2236 }

2237)

2238 

2239async for message in query(prompt="Analyze this codebase", options=options):

2240 print(message)

2241```

2242 

2243## Tool Input/Output Types

2244 

2245Documentation of input/output schemas for all built-in Claude Code tools. While the Python SDK doesn't export these as types, they represent the structure of tool inputs and outputs in messages.

2246 

2247### Agent

2248 

2249**Tool name:** `Agent` (previously `Task`, which is still accepted as an alias)

2250 

2251**Input:**

2252 

2253```python theme={null}

2254{

2255 "description": str, # A short (3-5 word) description of the task

2256 "prompt": str, # The task for the agent to perform

2257 "subagent_type": str, # The type of specialized agent to use

2258}

2259```

2260 

2261**Output:**

2262 

2263```python theme={null}

2264{

2265 "result": str, # Final result from the subagent

2266 "usage": dict | None, # Token usage statistics

2267 "total_cost_usd": float | None, # Estimated total cost in USD

2268 "duration_ms": int | None, # Execution duration in milliseconds

2269}

2270```

2271 

2272### AskUserQuestion

2273 

2274**Tool name:** `AskUserQuestion`

2275 

2276Asks the user clarifying questions during execution. See [Handle approvals and user input](/en/agent-sdk/user-input#handle-clarifying-questions) for usage details.

2277 

2278**Input:**

2279 

2280```python theme={null}

2281{

2282 "questions": [ # Questions to ask the user (1-4 questions)

2283 {

2284 "question": str, # The complete question to ask the user

2285 "header": str, # Very short label displayed as a chip/tag (max 12 chars)

2286 "options": [ # The available choices (2-4 options)

2287 {

2288 "label": str, # Display text for this option (1-5 words)

2289 "description": str, # Explanation of what this option means

2290 }

2291 ],

2292 "multiSelect": bool, # Set to true to allow multiple selections

2293 }

2294 ],

2295 "answers": dict | None, # User answers populated by the permission system

2296}

2297```

2298 

2299**Output:**

2300 

2301```python theme={null}

2302{

2303 "questions": [ # The questions that were asked

2304 {

2305 "question": str,

2306 "header": str,

2307 "options": [{"label": str, "description": str}],

2308 "multiSelect": bool,

2309 }

2310 ],

2311 "answers": dict[str, str], # Maps question text to answer string

2312 # Multi-select answers are comma-separated

2313}

2314```

2315 

2316### Bash

2317 

2318**Tool name:** `Bash`

2319 

2320**Input:**

2321 

2322```python theme={null}

2323{

2324 "command": str, # The command to execute

2325 "timeout": int | None, # Optional timeout in milliseconds (max 600000)

2326 "description": str | None, # Clear, concise description (5-10 words)

2327 "run_in_background": bool | None, # Set to true to run in background

2328}

2329```

2330 

2331**Output:**

2332 

2333```python theme={null}

2334{

2335 "output": str, # Combined stdout and stderr output

2336 "exitCode": int, # Exit code of the command

2337 "killed": bool | None, # Whether command was killed due to timeout

2338 "shellId": str | None, # Shell ID for background processes

2339}

2340```

2341 

2342### Monitor

2343 

2344**Tool name:** `Monitor`

2345 

2346Runs a background script and delivers each stdout line to Claude as an event so it can react without polling. Monitor follows the same permission rules as Bash. See the [Monitor tool reference](/en/tools-reference#monitor-tool) for behavior and provider availability.

2347 

2348**Input:**

2349 

2350```python theme={null}

2351{

2352 "command": str, # Shell script; each stdout line is an event, exit ends the watch

2353 "description": str, # Short description shown in notifications

2354 "timeout_ms": int | None, # Kill after this deadline (default 300000, max 3600000)

2355 "persistent": bool | None, # Run for the lifetime of the session; stop with TaskStop

2356}

2357```

2358 

2359**Output:**

2360 

2361```python theme={null}

2362{

2363 "taskId": str, # ID of the background monitor task

2364 "timeoutMs": int, # Timeout deadline in milliseconds (0 when persistent)

2365 "persistent": bool | None, # True when running until TaskStop or session end

2366}

2367```

2368 

2369### Edit

2370 

2371**Tool name:** `Edit`

2372 

2373**Input:**

2374 

2375```python theme={null}

2376{

2377 "file_path": str, # The absolute path to the file to modify

2378 "old_string": str, # The text to replace

2379 "new_string": str, # The text to replace it with

2380 "replace_all": bool | None, # Replace all occurrences (default False)

2381}

2382```

2383 

2384**Output:**

2385 

2386```python theme={null}

2387{

2388 "message": str, # Confirmation message

2389 "replacements": int, # Number of replacements made

2390 "file_path": str, # File path that was edited

2391}

2392```

2393 

2394### Read

2395 

2396**Tool name:** `Read`

2397 

2398**Input:**

2399 

2400```python theme={null}

2401{

2402 "file_path": str, # The absolute path to the file to read

2403 "offset": int | None, # The line number to start reading from

2404 "limit": int | None, # The number of lines to read

2405}

2406```

2407 

2408**Output (Text files):**

2409 

2410```python theme={null}

2411{

2412 "content": str, # File contents with line numbers

2413 "total_lines": int, # Total number of lines in file

2414 "lines_returned": int, # Lines actually returned

2415}

2416```

2417 

2418**Output (Images):**

2419 

2420```python theme={null}

2421{

2422 "image": str, # Base64 encoded image data

2423 "mime_type": str, # Image MIME type

2424 "file_size": int, # File size in bytes

2425}

2426```

2427 

2428### Write

2429 

2430**Tool name:** `Write`

2431 

2432**Input:**

2433 

2434```python theme={null}

2435{

2436 "file_path": str, # The absolute path to the file to write

2437 "content": str, # The content to write to the file

2438}

2439```

2440 

2441**Output:**

2442 

2443```python theme={null}

2444{

2445 "message": str, # Success message

2446 "bytes_written": int, # Number of bytes written

2447 "file_path": str, # File path that was written

2448}

2449```

2450 

2451### Glob

2452 

2453**Tool name:** `Glob`

2454 

2455**Input:**

2456 

2457```python theme={null}

2458{

2459 "pattern": str, # The glob pattern to match files against

2460 "path": str | None, # The directory to search in (defaults to cwd)

2461}

2462```

2463 

2464**Output:**

2465 

2466```python theme={null}

2467{

2468 "matches": list[str], # Array of matching file paths

2469 "count": int, # Number of matches found

2470 "search_path": str, # Search directory used

2471}

2472```

2473 

2474### Grep

2475 

2476**Tool name:** `Grep`

2477 

2478**Input:**

2479 

2480```python theme={null}

2481{

2482 "pattern": str, # The regular expression pattern

2483 "path": str | None, # File or directory to search in

2484 "glob": str | None, # Glob pattern to filter files

2485 "type": str | None, # File type to search

2486 "output_mode": str | None, # "content", "files_with_matches", or "count"

2487 "-i": bool | None, # Case insensitive search

2488 "-n": bool | None, # Show line numbers

2489 "-B": int | None, # Lines to show before each match

2490 "-A": int | None, # Lines to show after each match

2491 "-C": int | None, # Lines to show before and after

2492 "head_limit": int | None, # Limit output to first N lines/entries

2493 "multiline": bool | None, # Enable multiline mode

2494}

2495```

2496 

2497**Output (content mode):**

2498 

2499```python theme={null}

2500{

2501 "matches": [

2502 {

2503 "file": str,

2504 "line_number": int | None,

2505 "line": str,

2506 "before_context": list[str] | None,

2507 "after_context": list[str] | None,

2508 }

2509 ],

2510 "total_matches": int,

2511}

2512```

2513 

2514**Output (files\_with\_matches mode):**

2515 

2516```python theme={null}

2517{

2518 "files": list[str], # Files containing matches

2519 "count": int, # Number of files with matches

2520}

2521```

2522 

2523### NotebookEdit

2524 

2525**Tool name:** `NotebookEdit`

2526 

2527**Input:**

2528 

2529```python theme={null}

2530{

2531 "notebook_path": str, # Absolute path to the Jupyter notebook

2532 "cell_id": str | None, # The ID of the cell to edit

2533 "new_source": str, # The new source for the cell

2534 "cell_type": "code" | "markdown" | None, # The type of the cell

2535 "edit_mode": "replace" | "insert" | "delete" | None, # Edit operation type

2536}

2537```

2538 

2539**Output:**

2540 

2541```python theme={null}

2542{

2543 "message": str, # Success message

2544 "edit_type": "replaced" | "inserted" | "deleted", # Type of edit performed

2545 "cell_id": str | None, # Cell ID that was affected

2546 "total_cells": int, # Total cells in notebook after edit

2547}

2548```

2549 

2550### WebFetch

2551 

2552**Tool name:** `WebFetch`

2553 

2554**Input:**

2555 

2556```python theme={null}

2557{

2558 "url": str, # The URL to fetch content from

2559 "prompt": str, # The prompt to run on the fetched content

2560}

2561```

2562 

2563**Output:**

2564 

2565```python theme={null}

2566{

2567 "response": str, # AI model's response to the prompt

2568 "url": str, # URL that was fetched

2569 "final_url": str | None, # Final URL after redirects

2570 "status_code": int | None, # HTTP status code

2571}

2572```

2573 

2574### WebSearch

2575 

2576**Tool name:** `WebSearch`

2577 

2578**Input:**

2579 

2580```python theme={null}

2581{

2582 "query": str, # The search query to use

2583 "allowed_domains": list[str] | None, # Only include results from these domains

2584 "blocked_domains": list[str] | None, # Never include results from these domains

2585}

2586```

2587 

2588**Output:**

2589 

2590```python theme={null}

2591{

2592 "results": [{"title": str, "url": str, "snippet": str, "metadata": dict | None}],

2593 "total_results": int,

2594 "query": str,

2595}

2596```

2597 

2598### TodoWrite

2599 

2600**Tool name:** `TodoWrite`

2601 

2602**Input:**

2603 

2604```python theme={null}

2605{

2606 "todos": [

2607 {

2608 "content": str, # The task description

2609 "status": "pending" | "in_progress" | "completed", # Task status

2610 "activeForm": str, # Active form of the description

2611 }

2612 ]

2613}

2614```

2615 

2616**Output:**

2617 

2618```python theme={null}

2619{

2620 "message": str, # Success message

2621 "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},

2622}

2623```

2624 

2625### BashOutput

2626 

2627**Tool name:** `BashOutput`

2628 

2629**Input:**

2630 

2631```python theme={null}

2632{

2633 "bash_id": str, # The ID of the background shell

2634 "filter": str | None, # Optional regex to filter output lines

2635}

2636```

2637 

2638**Output:**

2639 

2640```python theme={null}

2641{

2642 "output": str, # New output since last check

2643 "status": "running" | "completed" | "failed", # Current shell status

2644 "exitCode": int | None, # Exit code when completed

2645}

2646```

2647 

2648### KillBash

2649 

2650**Tool name:** `KillBash`

2651 

2652**Input:**

2653 

2654```python theme={null}

2655{

2656 "shell_id": str # The ID of the background shell to kill

2657}

2658```

2659 

2660**Output:**

2661 

2662```python theme={null}

2663{

2664 "message": str, # Success message

2665 "shell_id": str, # ID of the killed shell

2666}

2667```

2668 

2669### ExitPlanMode

2670 

2671**Tool name:** `ExitPlanMode`

2672 

2673**Input:**

2674 

2675```python theme={null}

2676{

2677 "plan": str # The plan to run by the user for approval

2678}

2679```

2680 

2681**Output:**

2682 

2683```python theme={null}

2684{

2685 "message": str, # Confirmation message

2686 "approved": bool | None, # Whether user approved the plan

2687}

2688```

2689 

2690### ListMcpResources

2691 

2692**Tool name:** `ListMcpResources`

2693 

2694**Input:**

2695 

2696```python theme={null}

2697{

2698 "server": str | None # Optional server name to filter resources by

2699}

2700```

2701 

2702**Output:**

2703 

2704```python theme={null}

2705{

2706 "resources": [

2707 {

2708 "uri": str,

2709 "name": str,

2710 "description": str | None,

2711 "mimeType": str | None,

2712 "server": str,

2713 }

2714 ],

2715 "total": int,

2716}

2717```

2718 

2719### ReadMcpResource

2720 

2721**Tool name:** `ReadMcpResource`

2722 

2723**Input:**

2724 

2725```python theme={null}

2726{

2727 "server": str, # The MCP server name

2728 "uri": str, # The resource URI to read

2729}

2730```

2731 

2732**Output:**

2733 

2734```python theme={null}

2735{

2736 "contents": [

2737 {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None}

2738 ],

2739 "server": str,

2740}

2741```

2742 

2743## Advanced Features with ClaudeSDKClient

2744 

2745### Building a Continuous Conversation Interface

2746 

2747```python theme={null}

2748from claude_agent_sdk import (

2749 ClaudeSDKClient,

2750 ClaudeAgentOptions,

2751 AssistantMessage,

2752 TextBlock,

2753)

2754import asyncio

2755 

2756 

2757class ConversationSession:

2758 """Maintains a single conversation session with Claude."""

2759 

2760 def __init__(self, options: ClaudeAgentOptions | None = None):

2761 self.client = ClaudeSDKClient(options)

2762 self.turn_count = 0

2763 

2764 async def start(self):

2765 await self.client.connect()

2766 print("Starting conversation session. Claude will remember context.")

2767 print(

2768 "Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session"

2769 )

2770 

2771 while True:

2772 user_input = input(f"\n[Turn {self.turn_count + 1}] You: ")

2773 

2774 if user_input.lower() == "exit":

2775 break

2776 elif user_input.lower() == "interrupt":

2777 await self.client.interrupt()

2778 print("Task interrupted!")

2779 continue

2780 elif user_input.lower() == "new":

2781 # Disconnect and reconnect for a fresh session

2782 await self.client.disconnect()

2783 await self.client.connect()

2784 self.turn_count = 0

2785 print("Started new conversation session (previous context cleared)")

2786 continue

2787 

2788 # Send message - the session retains all previous messages

2789 await self.client.query(user_input)

2790 self.turn_count += 1

2791 

2792 # Process response

2793 print(f"[Turn {self.turn_count}] Claude: ", end="")

2794 async for message in self.client.receive_response():

2795 if isinstance(message, AssistantMessage):

2796 for block in message.content:

2797 if isinstance(block, TextBlock):

2798 print(block.text, end="")

2799 print() # New line after response

2800 

2801 await self.client.disconnect()

2802 print(f"Conversation ended after {self.turn_count} turns.")

2803 

2804 

2805async def main():

2806 options = ClaudeAgentOptions(

2807 allowed_tools=["Read", "Write", "Bash"], permission_mode="acceptEdits"

2808 )

2809 session = ConversationSession(options)

2810 await session.start()

2811 

2812 

2813# Example conversation:

2814# Turn 1 - You: "Create a file called hello.py"

2815# Turn 1 - Claude: "I'll create a hello.py file for you..."

2816# Turn 2 - You: "What's in that file?"

2817# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)

2818# Turn 3 - You: "Add a main function to it"

2819# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)

2820 

2821asyncio.run(main())

2822```

2823 

2824### Using Hooks for Behavior Modification

2825 

2826```python theme={null}

2827from claude_agent_sdk import (

2828 ClaudeSDKClient,

2829 ClaudeAgentOptions,

2830 HookMatcher,

2831 HookContext,

2832)

2833import asyncio

2834from typing import Any

2835 

2836 

2837async def pre_tool_logger(

2838 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext

2839) -> dict[str, Any]:

2840 """Log all tool usage before execution."""

2841 tool_name = input_data.get("tool_name", "unknown")

2842 print(f"[PRE-TOOL] About to use: {tool_name}")

2843 

2844 # You can modify or block the tool execution here

2845 if tool_name == "Bash" and "rm -rf" in str(input_data.get("tool_input", {})):

2846 return {

2847 "hookSpecificOutput": {

2848 "hookEventName": "PreToolUse",

2849 "permissionDecision": "deny",

2850 "permissionDecisionReason": "Dangerous command blocked",

2851 }

2852 }

2853 return {}

2854 

2855 

2856async def post_tool_logger(

2857 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext

2858) -> dict[str, Any]:

2859 """Log results after tool execution."""

2860 tool_name = input_data.get("tool_name", "unknown")

2861 print(f"[POST-TOOL] Completed: {tool_name}")

2862 return {}

2863 

2864 

2865async def user_prompt_modifier(

2866 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext

2867) -> dict[str, Any]:

2868 """Add context to user prompts."""

2869 original_prompt = input_data.get("prompt", "")

2870 

2871 # Add a timestamp as additional context for Claude to see

2872 from datetime import datetime

2873 

2874 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

2875 

2876 return {

2877 "hookSpecificOutput": {

2878 "hookEventName": "UserPromptSubmit",

2879 "additionalContext": f"[Submitted at {timestamp}] Original prompt: {original_prompt}",

2880 }

2881 }

2882 

2883 

2884async def main():

2885 options = ClaudeAgentOptions(

2886 hooks={

2887 "PreToolUse": [

2888 HookMatcher(hooks=[pre_tool_logger]),

2889 HookMatcher(matcher="Bash", hooks=[pre_tool_logger]),

2890 ],

2891 "PostToolUse": [HookMatcher(hooks=[post_tool_logger])],

2892 "UserPromptSubmit": [HookMatcher(hooks=[user_prompt_modifier])],

2893 },

2894 allowed_tools=["Read", "Write", "Bash"],

2895 )

2896 

2897 async with ClaudeSDKClient(options=options) as client:

2898 await client.query("List files in current directory")

2899 

2900 async for message in client.receive_response():

2901 # Hooks will automatically log tool usage

2902 pass

2903 

2904 

2905asyncio.run(main())

2906```

2907 

2908### Real-time Progress Monitoring

2909 

2910```python theme={null}

2911from claude_agent_sdk import (

2912 ClaudeSDKClient,

2913 ClaudeAgentOptions,

2914 AssistantMessage,

2915 ToolUseBlock,

2916 ToolResultBlock,

2917 TextBlock,

2918)

2919import asyncio

2920 

2921 

2922async def monitor_progress():

2923 options = ClaudeAgentOptions(

2924 allowed_tools=["Write", "Bash"], permission_mode="acceptEdits"

2925 )

2926 

2927 async with ClaudeSDKClient(options=options) as client:

2928 await client.query("Create 5 Python files with different sorting algorithms")

2929 

2930 # Monitor progress in real-time

2931 async for message in client.receive_response():

2932 if isinstance(message, AssistantMessage):

2933 for block in message.content:

2934 if isinstance(block, ToolUseBlock):

2935 if block.name == "Write":

2936 file_path = block.input.get("file_path", "")

2937 print(f"Creating: {file_path}")

2938 elif isinstance(block, ToolResultBlock):

2939 print("Completed tool execution")

2940 elif isinstance(block, TextBlock):

2941 print(f"Claude says: {block.text[:100]}...")

2942 

2943 print("Task completed!")

2944 

2945 

2946asyncio.run(monitor_progress())

2947```

2948 

2949## Example Usage

2950 

2951### Basic file operations (using query)

2952 

2953```python theme={null}

2954from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock

2955import asyncio

2956 

2957 

2958async def create_project():

2959 options = ClaudeAgentOptions(

2960 allowed_tools=["Read", "Write", "Bash"],

2961 permission_mode="acceptEdits",

2962 cwd="/home/user/project",

2963 )

2964 

2965 async for message in query(

2966 prompt="Create a Python project structure with setup.py", options=options

2967 ):

2968 if isinstance(message, AssistantMessage):

2969 for block in message.content:

2970 if isinstance(block, ToolUseBlock):

2971 print(f"Using tool: {block.name}")

2972 

2973 

2974asyncio.run(create_project())

2975```

2976 

2977### Error handling

2978 

2979```python theme={null}

2980from claude_agent_sdk import query, CLINotFoundError, ProcessError, CLIJSONDecodeError

2981 

2982try:

2983 async for message in query(prompt="Hello"):

2984 print(message)

2985except CLINotFoundError:

2986 print(

2987 "Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk"

2988 )

2989except ProcessError as e:

2990 print(f"Process failed with exit code: {e.exit_code}")

2991except CLIJSONDecodeError as e:

2992 print(f"Failed to parse response: {e}")

2993```

2994 

2995### Streaming mode with client

2996 

2997```python theme={null}

2998from claude_agent_sdk import ClaudeSDKClient

2999import asyncio

3000 

3001 

3002async def interactive_session():

3003 async with ClaudeSDKClient() as client:

3004 # Send initial message

3005 await client.query("What's the weather like?")

3006 

3007 # Process responses

3008 async for msg in client.receive_response():

3009 print(msg)

3010 

3011 # Send follow-up

3012 await client.query("Tell me more about that")

3013 

3014 # Process follow-up response

3015 async for msg in client.receive_response():

3016 print(msg)

3017 

3018 

3019asyncio.run(interactive_session())

3020```

3021 

3022### Using custom tools with ClaudeSDKClient

3023 

3024```python theme={null}

3025from claude_agent_sdk import (

3026 ClaudeSDKClient,

3027 ClaudeAgentOptions,

3028 tool,

3029 create_sdk_mcp_server,

3030 AssistantMessage,

3031 TextBlock,

3032)

3033import asyncio

3034from typing import Any

3035 

3036 

3037# Define custom tools with @tool decorator

3038@tool("calculate", "Perform mathematical calculations", {"expression": str})

3039async def calculate(args: dict[str, Any]) -> dict[str, Any]:

3040 try:

3041 result = eval(args["expression"], {"__builtins__": {}})

3042 return {"content": [{"type": "text", "text": f"Result: {result}"}]}

3043 except Exception as e:

3044 return {

3045 "content": [{"type": "text", "text": f"Error: {str(e)}"}],

3046 "is_error": True,

3047 }

3048 

3049 

3050@tool("get_time", "Get current time", {})

3051async def get_time(args: dict[str, Any]) -> dict[str, Any]:

3052 from datetime import datetime

3053 

3054 current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

3055 return {"content": [{"type": "text", "text": f"Current time: {current_time}"}]}

3056 

3057 

3058async def main():

3059 # Create SDK MCP server with custom tools

3060 my_server = create_sdk_mcp_server(

3061 name="utilities", version="1.0.0", tools=[calculate, get_time]

3062 )

3063 

3064 # Configure options with the server

3065 options = ClaudeAgentOptions(

3066 mcp_servers={"utils": my_server},

3067 allowed_tools=["mcp__utils__calculate", "mcp__utils__get_time"],

3068 )

3069 

3070 # Use ClaudeSDKClient for interactive tool usage

3071 async with ClaudeSDKClient(options=options) as client:

3072 await client.query("What's 123 * 456?")

3073 

3074 # Process calculation response

3075 async for message in client.receive_response():

3076 if isinstance(message, AssistantMessage):

3077 for block in message.content:

3078 if isinstance(block, TextBlock):

3079 print(f"Calculation: {block.text}")

3080 

3081 # Follow up with time query

3082 await client.query("What time is it now?")

3083 

3084 async for message in client.receive_response():

3085 if isinstance(message, AssistantMessage):

3086 for block in message.content:

3087 if isinstance(block, TextBlock):

3088 print(f"Time: {block.text}")

3089 

3090 

3091asyncio.run(main())

3092```

3093 

3094## Sandbox Configuration

3095 

3096### `SandboxSettings`

3097 

3098Configuration for sandbox behavior. Use this to enable command sandboxing and configure network restrictions programmatically.

3099 

3100```python theme={null}

3101class SandboxSettings(TypedDict, total=False):

3102 enabled: bool

3103 autoAllowBashIfSandboxed: bool

3104 excludedCommands: list[str]

3105 allowUnsandboxedCommands: bool

3106 network: SandboxNetworkConfig

3107 ignoreViolations: SandboxIgnoreViolations

3108 enableWeakerNestedSandbox: bool

3109```

3110 

3111| Property | Type | Default | Description |

3112| :-------------------------- | :------------------------------------------------------ | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

3113| `enabled` | `bool` | `False` | Enable sandbox mode for command execution |

3114| `autoAllowBashIfSandboxed` | `bool` | `True` | Auto-approve bash commands when sandbox is enabled |

3115| `excludedCommands` | `list[str]` | `[]` | Commands that always bypass sandbox restrictions (e.g., `["docker"]`). These run unsandboxed automatically without model involvement |

3116| `allowUnsandboxedCommands` | `bool` | `True` | Allow the model to request running commands outside the sandbox. When `True`, the model can set `dangerouslyDisableSandbox` in tool input, which falls back to the [permissions system](#permissions-fallback-for-unsandboxed-commands) |

3117| `network` | [`SandboxNetworkConfig`](#sandbox-network-config) | `None` | Network-specific sandbox configuration |

3118| `ignoreViolations` | [`SandboxIgnoreViolations`](#sandbox-ignore-violations) | `None` | Configure which sandbox violations to ignore |

3119| `enableWeakerNestedSandbox` | `bool` | `False` | Enable a weaker nested sandbox for compatibility |

3120 

3121<Note>

3122 **Filesystem and network access restrictions** are NOT configured via sandbox settings. Instead, they are derived from [permission rules](/en/settings#permission-settings):

3123 

3124 * **Filesystem read restrictions**: Read deny rules

3125 * **Filesystem write restrictions**: Edit allow/deny rules

3126 * **Network restrictions**: WebFetch allow/deny rules

3127 

3128 Use sandbox settings for command execution sandboxing, and permission rules for filesystem and network access control.

3129</Note>

3130 

3131#### Example usage

3132 

3133```python theme={null}

3134from claude_agent_sdk import query, ClaudeAgentOptions, SandboxSettings

3135 

3136sandbox_settings: SandboxSettings = {

3137 "enabled": True,

3138 "autoAllowBashIfSandboxed": True,

3139 "network": {"allowLocalBinding": True},

3140}

3141 

3142async for message in query(

3143 prompt="Build and test my project",

3144 options=ClaudeAgentOptions(sandbox=sandbox_settings),

3145):

3146 print(message)

3147```

3148 

3149<Warning>

3150 **Unix socket security**: The `allowUnixSockets` option can grant access to powerful system services. For example, allowing `/var/run/docker.sock` effectively grants full host system access through the Docker API, bypassing sandbox isolation. Only allow Unix sockets that are strictly necessary and understand the security implications of each.

3151</Warning>

3152 

3153### `SandboxNetworkConfig`

3154 

3155Network-specific configuration for sandbox mode.

3156 

3157```python theme={null}

3158class SandboxNetworkConfig(TypedDict, total=False):

3159 allowLocalBinding: bool

3160 allowUnixSockets: list[str]

3161 allowAllUnixSockets: bool

3162 httpProxyPort: int

3163 socksProxyPort: int

3164```

3165 

3166| Property | Type | Default | Description |

3167| :-------------------- | :---------- | :------ | :---------------------------------------------------------------- |

3168| `allowLocalBinding` | `bool` | `False` | Allow processes to bind to local ports (e.g., for dev servers) |

3169| `allowUnixSockets` | `list[str]` | `[]` | Unix socket paths that processes can access (e.g., Docker socket) |

3170| `allowAllUnixSockets` | `bool` | `False` | Allow access to all Unix sockets |

3171| `httpProxyPort` | `int` | `None` | HTTP proxy port for network requests |

3172| `socksProxyPort` | `int` | `None` | SOCKS proxy port for network requests |

3173 

3174### `SandboxIgnoreViolations`

3175 

3176Configuration for ignoring specific sandbox violations.

3177 

3178```python theme={null}

3179class SandboxIgnoreViolations(TypedDict, total=False):

3180 file: list[str]

3181 network: list[str]

3182```

3183 

3184| Property | Type | Default | Description |

3185| :-------- | :---------- | :------ | :------------------------------------------ |

3186| `file` | `list[str]` | `[]` | File path patterns to ignore violations for |

3187| `network` | `list[str]` | `[]` | Network patterns to ignore violations for |

3188 

3189### Permissions Fallback for Unsandboxed Commands

3190 

3191When `allowUnsandboxedCommands` is enabled, the model can request to run commands outside the sandbox by setting `dangerouslyDisableSandbox: True` in the tool input. These requests fall back to the existing permissions system, meaning your `can_use_tool` handler will be invoked, allowing you to implement custom authorization logic.

3192 

3193<Note>

3194 **`excludedCommands` vs `allowUnsandboxedCommands`:**

3195 

3196 * `excludedCommands`: A static list of commands that always bypass the sandbox automatically (e.g., `["docker"]`). The model has no control over this.

3197 * `allowUnsandboxedCommands`: Lets the model decide at runtime whether to request unsandboxed execution by setting `dangerouslyDisableSandbox: True` in the tool input.

3198</Note>

3199 

3200```python theme={null}

3201from claude_agent_sdk import (

3202 query,

3203 ClaudeAgentOptions,

3204 HookMatcher,

3205 PermissionResultAllow,

3206 PermissionResultDeny,

3207 ToolPermissionContext,

3208)

3209 

3210 

3211async def can_use_tool(

3212 tool: str, input: dict, context: ToolPermissionContext

3213) -> PermissionResultAllow | PermissionResultDeny:

3214 # Check if the model is requesting to bypass the sandbox

3215 if tool == "Bash" and input.get("dangerouslyDisableSandbox"):

3216 # The model is requesting to run this command outside the sandbox

3217 print(f"Unsandboxed command requested: {input.get('command')}")

3218 

3219 if is_command_authorized(input.get("command")):

3220 return PermissionResultAllow()

3221 return PermissionResultDeny(

3222 message="Command not authorized for unsandboxed execution"

3223 )

3224 return PermissionResultAllow()

3225 

3226 

3227# Required: dummy hook keeps the stream open for can_use_tool

3228async def dummy_hook(input_data, tool_use_id, context):

3229 return {"continue_": True}

3230 

3231 

3232async def prompt_stream():

3233 yield {

3234 "type": "user",

3235 "message": {"role": "user", "content": "Deploy my application"},

3236 }

3237 

3238 

3239async def main():

3240 async for message in query(

3241 prompt=prompt_stream(),

3242 options=ClaudeAgentOptions(

3243 sandbox={

3244 "enabled": True,

3245 "allowUnsandboxedCommands": True, # Model can request unsandboxed execution

3246 },

3247 permission_mode="default",

3248 can_use_tool=can_use_tool,

3249 hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},

3250 ),

3251 ):

3252 print(message)

3253```

3254 

3255This pattern enables you to:

3256 

3257* **Audit model requests**: Log when the model requests unsandboxed execution

3258* **Implement allowlists**: Only permit specific commands to run unsandboxed

3259* **Add approval workflows**: Require explicit authorization for privileged operations

3260 

3261<Warning>

3262 Commands running with `dangerouslyDisableSandbox: True` have full system access. Ensure your `can_use_tool` handler validates these requests carefully.

3263 

3264 If `permission_mode` is set to `bypassPermissions` and `allow_unsandboxed_commands` is enabled, the model can autonomously execute commands outside the sandbox without any approval prompts. This combination effectively allows the model to escape sandbox isolation silently.

3265</Warning>

3266 

3267## See also

3268 

3269* [SDK overview](/en/agent-sdk/overview) - General SDK concepts

3270* [TypeScript SDK reference](/en/agent-sdk/typescript) - TypeScript SDK documentation

3271* [CLI reference](/en/cli-reference) - Command-line interface

3272* [Common workflows](/en/common-workflows) - Step-by-step guides

agent-sdk/quickstart.md +333 −0 added

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# Quickstart

6 

7> Get started with the Python or TypeScript Agent SDK to build AI agents that work autonomously

8 

9Use the Agent SDK to build an AI agent that reads your code, finds bugs, and fixes them, all without manual intervention.

10 

11**What you'll do:**

12 

131. Set up a project with the Agent SDK

142. Create a file with some buggy code

153. Run an agent that finds and fixes the bugs automatically

16 

17## Prerequisites

18 

19* **Node.js 18+** or **Python 3.10+**

20* An **Anthropic account** ([sign up here](https://platform.claude.com/))

21 

22## Setup

23 

24<Steps>

25 <Step title="Create a project folder">

26 Create a new directory for this quickstart:

27 

28 ```bash theme={null}

29 mkdir my-agent && cd my-agent

30 ```

31 

32 For your own projects, you can run the SDK from any folder; it will have access to files in that directory and its subdirectories by default.

33 </Step>

34 

35 <Step title="Install the SDK">

36 Install the Agent SDK package for your language:

37 

38 <Tabs>

39 <Tab title="TypeScript">

40 ```bash theme={null}

41 npm install @anthropic-ai/claude-agent-sdk

42 ```

43 </Tab>

44 

45 <Tab title="Python (uv)">

46 [uv Python package manager](https://docs.astral.sh/uv/) is a fast Python package manager that handles virtual environments automatically:

47 

48 ```bash theme={null}

49 uv init && uv add claude-agent-sdk

50 ```

51 </Tab>

52 

53 <Tab title="Python (pip)">

54 Create a virtual environment first, then install:

55 

56 ```bash theme={null}

57 python3 -m venv .venv && source .venv/bin/activate

58 pip3 install claude-agent-sdk

59 ```

60 </Tab>

61 </Tabs>

62 

63 <Note>

64 The TypeScript SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don't need to install Claude Code separately.

65 </Note>

66 </Step>

67 

68 <Step title="Set your API key">

69 Get an API key from the [Claude Console](https://platform.claude.com/), then create a `.env` file in your project directory:

70 

71 ```bash theme={null}

72 ANTHROPIC_API_KEY=your-api-key

73 ```

74 

75 The SDK also supports authentication via third-party API providers:

76 

77 * **Amazon Bedrock**: set `CLAUDE_CODE_USE_BEDROCK=1` environment variable and configure AWS credentials

78 * **Google Vertex AI**: set `CLAUDE_CODE_USE_VERTEX=1` environment variable and configure Google Cloud credentials

79 * **Microsoft Azure**: set `CLAUDE_CODE_USE_FOUNDRY=1` environment variable and configure Azure credentials

80 

81 See the setup guides for [Bedrock](/en/amazon-bedrock), [Vertex AI](/en/google-vertex-ai), or [Azure AI Foundry](/en/microsoft-foundry) for details.

82 

83 <Note>

84 Unless previously approved, Anthropic does not allow third party developers to offer claude.ai login or rate limits for their products, including agents built on the Claude Agent SDK. Please use the API key authentication methods described in this document instead.

85 </Note>

86 </Step>

87</Steps>

88 

89## Create a buggy file

90 

91This quickstart walks you through building an agent that can find and fix bugs in code. First, you need a file with some intentional bugs for the agent to fix. Create `utils.py` in the `my-agent` directory and paste the following code:

92 

93```python theme={null}

94def calculate_average(numbers):

95 total = 0

96 for num in numbers:

97 total += num

98 return total / len(numbers)

99 

100 

101def get_user_name(user):

102 return user["name"].upper()

103```

104 

105This code has two bugs:

106 

1071. `calculate_average([])` crashes with division by zero

1082. `get_user_name(None)` crashes with a TypeError

109 

110## Build an agent that finds and fixes bugs

111 

112Create `agent.py` if you're using the Python SDK, or `agent.ts` for TypeScript:

113 

114<CodeGroup>

115 ```python Python theme={null}

116 import asyncio

117 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage

118 

119 

120 async def main():

121 # Agentic loop: streams messages as Claude works

122 async for message in query(

123 prompt="Review utils.py for bugs that would cause crashes. Fix any issues you find.",

124 options=ClaudeAgentOptions(

125 allowed_tools=["Read", "Edit", "Glob"], # Tools Claude can use

126 permission_mode="acceptEdits", # Auto-approve file edits

127 ),

128 ):

129 # Print human-readable output

130 if isinstance(message, AssistantMessage):

131 for block in message.content:

132 if hasattr(block, "text"):

133 print(block.text) # Claude's reasoning

134 elif hasattr(block, "name"):

135 print(f"Tool: {block.name}") # Tool being called

136 elif isinstance(message, ResultMessage):

137 print(f"Done: {message.subtype}") # Final result

138 

139 

140 asyncio.run(main())

141 ```

142 

143 ```typescript TypeScript theme={null}

144 import { query } from "@anthropic-ai/claude-agent-sdk";

145 

146 // Agentic loop: streams messages as Claude works

147 for await (const message of query({

148 prompt: "Review utils.py for bugs that would cause crashes. Fix any issues you find.",

149 options: {

150 allowedTools: ["Read", "Edit", "Glob"], // Tools Claude can use

151 permissionMode: "acceptEdits" // Auto-approve file edits

152 }

153 })) {

154 // Print human-readable output

155 if (message.type === "assistant" && message.message?.content) {

156 for (const block of message.message.content) {

157 if ("text" in block) {

158 console.log(block.text); // Claude's reasoning

159 } else if ("name" in block) {

160 console.log(`Tool: ${block.name}`); // Tool being called

161 }

162 }

163 } else if (message.type === "result") {

164 console.log(`Done: ${message.subtype}`); // Final result

165 }

166 }

167 ```

168</CodeGroup>

169 

170This code has three main parts:

171 

1721. **`query`**: the main entry point that creates the agentic loop. It returns an async iterator, so you use `async for` to stream messages as Claude works. See the full API in the [Python](/en/agent-sdk/python#query) or [TypeScript](/en/agent-sdk/typescript#query) SDK reference.

173 

1742. **`prompt`**: what you want Claude to do. Claude figures out which tools to use based on the task.

175 

1763. **`options`**: configuration for the agent. This example uses `allowedTools` to pre-approve `Read`, `Edit`, and `Glob`, and `permissionMode: "acceptEdits"` to auto-approve file changes. Other options include `systemPrompt`, `mcpServers`, and more. See all options for [Python](/en/agent-sdk/python#claude-agent-options) or [TypeScript](/en/agent-sdk/typescript#options).

177 

178The `async for` loop keeps running as Claude thinks, calls tools, observes results, and decides what to do next. Each iteration yields a message: Claude's reasoning, a tool call, a tool result, or the final outcome. The SDK handles the orchestration (tool execution, context management, retries) so you just consume the stream. The loop ends when Claude finishes the task or hits an error.

179 

180The message handling inside the loop filters for human-readable output. Without filtering, you'd see raw message objects including system initialization and internal state, which is useful for debugging but noisy otherwise.

181 

182<Note>

183 This example uses streaming to show progress in real-time. If you don't need live output (e.g., for background jobs or CI pipelines), you can collect all messages at once. See [Streaming vs. single-turn mode](/en/agent-sdk/streaming-vs-single-mode) for details.

184</Note>

185 

186### Run your agent

187 

188Your agent is ready. Run it with the following command:

189 

190<Tabs>

191 <Tab title="Python">

192 ```bash theme={null}

193 python3 agent.py

194 ```

195 </Tab>

196 

197 <Tab title="TypeScript">

198 ```bash theme={null}

199 npx tsx agent.ts

200 ```

201 </Tab>

202</Tabs>

203 

204After running, check `utils.py`. You'll see defensive code handling empty lists and null users. Your agent autonomously:

205 

2061. **Read** `utils.py` to understand the code

2072. **Analyzed** the logic and identified edge cases that would crash

2083. **Edited** the file to add proper error handling

209 

210This is what makes the Agent SDK different: Claude executes tools directly instead of asking you to implement them.

211 

212<Note>

213 If you see "API key not found", make sure you've set the `ANTHROPIC_API_KEY` environment variable in your `.env` file or shell environment. See the [full troubleshooting guide](/en/troubleshooting) for more help.

214</Note>

215 

216### Try other prompts

217 

218Now that your agent is set up, try some different prompts:

219 

220* `"Add docstrings to all functions in utils.py"`

221* `"Add type hints to all functions in utils.py"`

222* `"Create a README.md documenting the functions in utils.py"`

223 

224### Customize your agent

225 

226You can modify your agent's behavior by changing the options. Here are a few examples:

227 

228**Add web search capability:**

229 

230<CodeGroup>

231 ```python Python theme={null}

232 options = ClaudeAgentOptions(

233 allowed_tools=["Read", "Edit", "Glob", "WebSearch"], permission_mode="acceptEdits"

234 )

235 ```

236 

237 ```typescript TypeScript hidelines={1,-1} theme={null}

238 const _ = {

239 options: {

240 allowedTools: ["Read", "Edit", "Glob", "WebSearch"],

241 permissionMode: "acceptEdits"

242 }

243 };

244 ```

245</CodeGroup>

246 

247**Give Claude a custom system prompt:**

248 

249<CodeGroup>

250 ```python Python theme={null}

251 options = ClaudeAgentOptions(

252 allowed_tools=["Read", "Edit", "Glob"],

253 permission_mode="acceptEdits",

254 system_prompt="You are a senior Python developer. Always follow PEP 8 style guidelines.",

255 )

256 ```

257 

258 ```typescript TypeScript hidelines={1,-1} theme={null}

259 const _ = {

260 options: {

261 allowedTools: ["Read", "Edit", "Glob"],

262 permissionMode: "acceptEdits",

263 systemPrompt: "You are a senior Python developer. Always follow PEP 8 style guidelines."

264 }

265 };

266 ```

267</CodeGroup>

268 

269**Run commands in the terminal:**

270 

271<CodeGroup>

272 ```python Python theme={null}

273 options = ClaudeAgentOptions(

274 allowed_tools=["Read", "Edit", "Glob", "Bash"], permission_mode="acceptEdits"

275 )

276 ```

277 

278 ```typescript TypeScript hidelines={1,-1} theme={null}

279 const _ = {

280 options: {

281 allowedTools: ["Read", "Edit", "Glob", "Bash"],

282 permissionMode: "acceptEdits"

283 }

284 };

285 ```

286</CodeGroup>

287 

288With `Bash` enabled, try: `"Write unit tests for utils.py, run them, and fix any failures"`

289 

290## Key concepts

291 

292**Tools** control what your agent can do:

293 

294| Tools | What the agent can do |

295| -------------------------------------- | ----------------------- |

296| `Read`, `Glob`, `Grep` | Read-only analysis |

297| `Read`, `Edit`, `Glob` | Analyze and modify code |

298| `Read`, `Edit`, `Bash`, `Glob`, `Grep` | Full automation |

299 

300**Permission modes** control how much human oversight you want:

301 

302| Mode | Behavior | Use case |

303| ------------------------ | ------------------------------------------------------------------------------- | ---------------------------------------- |

304| `acceptEdits` | Auto-approves file edits and common filesystem commands, asks for other actions | Trusted development workflows |

305| `dontAsk` | Denies anything not in `allowedTools` | Locked-down headless agents |

306| `auto` (TypeScript only) | A model classifier approves or denies each tool call | Autonomous agents with safety guardrails |

307| `bypassPermissions` | Runs every tool without prompts | Sandboxed CI, fully trusted environments |

308| `default` | Requires a `canUseTool` callback to handle approval | Custom approval flows |

309 

310The example above uses `acceptEdits` mode, which auto-approves file operations so the agent can run without interactive prompts. If you want to prompt users for approval, use `default` mode and provide a [`canUseTool` callback](/en/agent-sdk/user-input) that collects user input. For more control, see [Permissions](/en/agent-sdk/permissions).

311 

312## Troubleshooting

313 

314### API error `thinking.type.enabled` is not supported for this model

315 

316Claude Opus 4.7 replaces `thinking.type.enabled` with `thinking.type.adaptive`. Older Agent SDK versions fail with the following API error when you select `claude-opus-4-7`:

317 

318```text theme={null}

319API Error: 400 {"type":"invalid_request_error","message":"\"thinking.type.enabled\" is not supported for this model. Use \"thinking.type.adaptive\" and \"output_config.effort\" to control thinking behavior."}

320```

321 

322Upgrade to Agent SDK v0.2.111 or later to use Opus 4.7.

323 

324## Next steps

325 

326Now that you've created your first agent, learn how to extend its capabilities and tailor it to your use case:

327 

328* **[Permissions](/en/agent-sdk/permissions)**: control what your agent can do and when it needs approval

329* **[Hooks](/en/agent-sdk/hooks)**: run custom code before or after tool calls

330* **[Sessions](/en/agent-sdk/sessions)**: build multi-turn agents that maintain context

331* **[MCP servers](/en/agent-sdk/mcp)**: connect to databases, browsers, APIs, and other external systems

332* **[Hosting](/en/agent-sdk/hosting)**: deploy agents to Docker, cloud, and CI/CD

333* **[Example agents](https://github.com/anthropics/claude-agent-sdk-demos)**: see complete examples: email assistant, research agent, and more

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# Securely deploying AI agents

6 

7> A guide to securing Claude Code and Agent SDK deployments with isolation, credential management, and network controls

8 

9Claude Code and the Agent SDK are powerful tools that can execute code, access files, and interact with external services on your behalf. Like any tool with these capabilities, deploying them thoughtfully ensures you get the benefits while maintaining appropriate controls.

10 

11Unlike traditional software that follows predetermined code paths, these tools generate their actions dynamically based on context and goals. This flexibility is what makes them useful, but it also means their behavior can be influenced by the content they process: files, webpages, or user input. This is sometimes called prompt injection. For example, if a repository's README contains unusual instructions, Claude Code might incorporate those into its actions in ways the operator didn't anticipate. This guide covers practical ways to reduce this risk.

12 

13The good news is that securing an agent deployment doesn't require exotic infrastructure. The same principles that apply to running any semi-trusted code apply here: isolation, least privilege, and defense in depth. Claude Code includes several security features that help with common concerns, and this guide walks through these along with additional hardening options for those who need them.

14 

15Not every deployment needs maximum security. A developer running Claude Code on their laptop has different requirements than a company processing customer data in a multi-tenant environment. This guide presents options ranging from Claude Code's built-in security features to hardened production architectures, so you can choose what fits your situation.

16 

17## Threat model

18 

19Agents can take unintended actions due to prompt injection (instructions embedded in content they process) or model error. Claude models are designed to resist this; see the [model overview](https://platform.claude.com/docs/en/about-claude/models/overview) and the system card for the model you deploy for evaluation details.

20 

21Defense in depth is still good practice though. For example, if an agent processes a malicious file that instructs it to send customer data to an external server, network controls can block that request entirely.

22 

23## Built-in security features

24 

25Claude Code includes several security features that address common concerns. See the [security documentation](/en/security) for full details.

26 

27* **Permissions system**: Every tool and bash command can be configured to allow, block, or prompt the user for approval. Use glob patterns to create rules like "allow all npm commands" or "block any command with sudo". Organizations can set policies that apply across all users. See [permissions](/en/permissions).

28* **Command parsing for permissions**: Before executing bash commands, Claude Code parses them into an AST and matches the result against your permission rules. Commands that cannot be parsed cleanly, or that do not match an allow rule, require explicit approval. A small set of constructs such as `eval` always require approval regardless of allow rules. This is a permission gate, not a sandbox; it does not infer whether a command is dangerous from its target path or effects.

29* **Web search summarization**: Search results are summarized rather than passing raw content directly into the context, reducing the risk of prompt injection from malicious web content.

30* **Sandbox mode**: Bash commands can run in a sandboxed environment that restricts filesystem and network access. See the [sandboxing documentation](/en/sandboxing) for details.

31 

32## Security principles

33 

34For deployments that require additional hardening beyond Claude Code's defaults, these principles guide the available options.

35 

36### Security boundaries

37 

38A security boundary separates components with different trust levels. For high-security deployments, you can place sensitive resources (like credentials) outside the boundary containing the agent. If something goes wrong in the agent's environment, resources outside that boundary remain protected.

39 

40For example, rather than giving an agent direct access to an API key, you could run a proxy outside the agent's environment that injects the key into requests. The agent can make API calls, but it never sees the credential itself. This pattern is useful for multi-tenant deployments or when processing untrusted content.

41 

42### Least privilege

43 

44When needed, you can restrict the agent to only the capabilities required for its specific task:

45 

46| Resource | Restriction options |

47| ------------------- | ----------------------------------------------- |

48| Filesystem | Mount only needed directories, prefer read-only |

49| Network | Restrict to specific endpoints via proxy |

50| Credentials | Inject via proxy rather than exposing directly |

51| System capabilities | Drop Linux capabilities in containers |

52 

53### Defense in depth

54 

55For high-security environments, layering multiple controls provides additional protection. Options include:

56 

57* Container isolation

58* Network restrictions

59* Filesystem controls

60* Request validation at a proxy

61 

62The right combination depends on your threat model and operational requirements.

63 

64## Isolation technologies

65 

66Different isolation technologies offer different tradeoffs between security strength, performance, and operational complexity.

67 

68<Info>

69 In all of these configurations, Claude Code (or your Agent SDK application) runs inside the isolation boundary (the sandbox, container, or VM). The security controls described below restrict what the agent can access from within that boundary.

70</Info>

71 

72| Technology | Isolation strength | Performance overhead | Complexity |

73| ----------------------- | ------------------------------ | -------------------- | ----------- |

74| Sandbox runtime | Good (secure defaults) | Very low | Low |

75| Containers (Docker) | Setup dependent | Low | Medium |

76| gVisor | Excellent (with correct setup) | Medium/High | Medium |

77| VMs (Firecracker, QEMU) | Excellent (with correct setup) | High | Medium/High |

78 

79### Sandbox runtime

80 

81For lightweight isolation without containers, [sandbox-runtime](https://github.com/anthropic-experimental/sandbox-runtime) enforces filesystem and network restrictions at the OS level.

82 

83The main advantage is simplicity: no Docker configuration, container images, or networking setup required. The proxy and filesystem restrictions are built in. You provide a settings file specifying allowed domains and paths.

84 

85**How it works:**

86 

87* **Filesystem**: Uses OS primitives (`bubblewrap` on Linux, `sandbox-exec` on macOS) to restrict read/write access to configured paths

88* **Network**: Removes network namespace (Linux) or uses Seatbelt profiles (macOS) to route network traffic through a built-in proxy

89* **Configuration**: JSON-based allowlists for domains and filesystem paths

90 

91**Setup:**

92 

93```bash theme={null}

94npm install @anthropic-ai/sandbox-runtime

95```

96 

97Then create a configuration file specifying allowed paths and domains.

98 

99**Security considerations:**

100 

1011. **Same-host kernel**: Unlike VMs, sandboxed processes share the host kernel. A kernel vulnerability could theoretically enable escape. For some threat models this is acceptable, but if you need kernel-level isolation, use gVisor or a separate VM.

102 

1032. **No TLS inspection**: The proxy allowlists domains but doesn't inspect encrypted traffic. If the agent has permissive credentials for an allowed domain, ensure it isn't possible to use that domain to trigger other network requests or to exfiltrate data.

104 

105For many single-developer and CI/CD use cases, sandbox-runtime raises the bar significantly with minimal setup. The sections below cover containers and VMs for deployments requiring stronger isolation.

106 

107### Containers

108 

109Containers provide isolation through Linux namespaces. Each container has its own view of the filesystem, process tree, and network stack, while sharing the host kernel.

110 

111A security-hardened container configuration might look like this:

112 

113```bash theme={null}

114docker run \

115 --cap-drop ALL \

116 --security-opt no-new-privileges \

117 --security-opt seccomp=/path/to/seccomp-profile.json \

118 --read-only \

119 --tmpfs /tmp:rw,noexec,nosuid,size=100m \

120 --tmpfs /home/agent:rw,noexec,nosuid,size=500m \

121 --network none \

122 --memory 2g \

123 --cpus 2 \

124 --pids-limit 100 \

125 --user 1000:1000 \

126 -v /path/to/code:/workspace:ro \

127 -v /var/run/proxy.sock:/var/run/proxy.sock:ro \

128 agent-image

129```

130 

131Here's what each option does:

132 

133| Option | Purpose |

134| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |

135| `--cap-drop ALL` | Removes Linux capabilities like `NET_ADMIN` and `SYS_ADMIN` that could enable privilege escalation |

136| `--security-opt no-new-privileges` | Prevents processes from gaining privileges through setuid binaries |

137| `--security-opt seccomp=...` | Restricts available syscalls; Docker's default blocks \~44, custom profiles can block more |

138| `--read-only` | Makes the container's root filesystem immutable, preventing the agent from persisting changes |

139| `--tmpfs /tmp:...` | Provides a writable temporary directory that's cleared when the container stops |

140| `--network none` | Removes all network interfaces; the agent communicates through the mounted Unix socket below |

141| `--memory 2g` | Limits memory usage to prevent resource exhaustion |

142| `--pids-limit 100` | Limits process count to prevent fork bombs |

143| `--user 1000:1000` | Runs as a non-root user |

144| `-v ...:/workspace:ro` | Mounts code read-only so the agent can analyze but not modify it. **Avoid mounting sensitive host directories like `~/.ssh`, `~/.aws`, or `~/.config`** |

145| `-v .../proxy.sock:...` | Mounts a Unix socket connected to a proxy running outside the container (see below) |

146 

147**Unix socket architecture:**

148 

149With `--network none`, the container has no network interfaces at all. The only way for the agent to reach the outside world is through the mounted Unix socket, which connects to a proxy running on the host. This proxy can enforce domain allowlists, inject credentials, and log all traffic.

150 

151This is the same architecture used by [sandbox-runtime](https://github.com/anthropic-experimental/sandbox-runtime). Even if the agent is compromised via prompt injection, it cannot exfiltrate data to arbitrary servers. It can only communicate through the proxy, which controls what domains are reachable. For more details, see the [Claude Code sandboxing blog post](https://www.anthropic.com/engineering/claude-code-sandboxing).

152 

153**Additional hardening options:**

154 

155| Option | Purpose |

156| ---------------- | -------------------------------------------------------------------------------------------------------------------- |

157| `--userns-remap` | Maps container root to unprivileged host user; requires daemon configuration but limits damage from container escape |

158| `--ipc private` | Isolates inter-process communication to prevent cross-container attacks |

159 

160### gVisor

161 

162Standard containers share the host kernel: when code inside a container makes a system call, it goes directly to the same kernel that runs the host. This means a kernel vulnerability could allow container escape. gVisor addresses this by intercepting system calls in userspace before they reach the host kernel, implementing its own compatibility layer that handles most syscalls without involving the real kernel.

163 

164If an agent runs malicious code (perhaps due to prompt injection), that code runs in the container and could attempt kernel exploits. With gVisor, the attack surface is much smaller: the malicious code would need to exploit gVisor's userspace implementation first and would have limited access to the real kernel.

165 

166To use gVisor with Docker, install the `runsc` runtime and configure the daemon:

167 

168```json theme={null}

169// /etc/docker/daemon.json

170{

171 "runtimes": {

172 "runsc": {

173 "path": "/usr/local/bin/runsc"

174 }

175 }

176}

177```

178 

179Then run containers with:

180 

181```bash theme={null}

182docker run --runtime=runsc agent-image

183```

184 

185**Performance considerations:**

186 

187| Workload | Overhead |

188| --------------------- | -------------------------------------------------- |

189| CPU-bound computation | \~0% (no syscall interception) |

190| Simple syscalls | \~2× slower |

191| File I/O intensive | Up to 10-200× slower for heavy open/close patterns |

192 

193For multi-tenant environments or when processing untrusted content, the additional isolation is often worth the overhead.

194 

195### Virtual machines

196 

197VMs provide hardware-level isolation through CPU virtualization extensions. Each VM runs its own kernel, creating a strong boundary. A vulnerability in the guest kernel doesn't directly compromise the host. However, VMs aren't automatically "more secure" than alternatives like gVisor. VM security depends heavily on the hypervisor and device emulation code.

198 

199Firecracker is designed for lightweight microVM isolation. It can boot VMs in under 125ms with less than 5 MiB memory overhead, stripping away unnecessary device emulation to reduce attack surface.

200 

201With this approach, the agent VM has no external network interface. Instead, it communicates through `vsock` (virtual sockets). All traffic routes through vsock to a proxy on the host, which enforces allowlists and injects credentials before forwarding requests.

202 

203### Cloud deployments

204 

205For cloud deployments, you can combine any of the above isolation technologies with cloud-native network controls:

206 

2071. Run agent containers in a private subnet with no internet gateway

2082. Configure cloud firewall rules (AWS Security Groups, GCP VPC firewall) to block all egress except to your proxy

2093. Run a proxy (such as [Envoy](https://www.envoyproxy.io/) with its `credential_injector` filter) that validates requests, enforces domain allowlists, injects credentials, and forwards to external APIs

2104. Assign minimal IAM permissions to the agent's service account, routing sensitive access through the proxy where possible

2115. Log all traffic at the proxy for audit purposes

212 

213## Credential management

214 

215Agents often need credentials to call APIs, access repositories, or interact with cloud services. The challenge is providing this access without exposing the credentials themselves.

216 

217### The proxy pattern

218 

219The recommended approach is to run a proxy outside the agent's security boundary that injects credentials into outgoing requests. The agent sends requests without credentials, the proxy adds them, and forwards the request to its destination.

220 

221This pattern has several benefits:

222 

2231. The agent never sees the actual credentials

2242. The proxy can enforce an allowlist of permitted endpoints

2253. The proxy can log all requests for auditing

2264. Credentials are stored in one secure location rather than distributed to each agent

227 

228### Configuring Claude Code to use a proxy

229 

230Claude Code supports two methods for routing sampling requests through a proxy:

231 

232**Option 1: ANTHROPIC\_BASE\_URL (simple but only for sampling API requests)**

233 

234```bash theme={null}

235export ANTHROPIC_BASE_URL="http://localhost:8080"

236```

237 

238This tells Claude Code and the Agent SDK to send sampling requests to your proxy instead of the Claude API directly. Your proxy receives plaintext HTTP requests, can inspect and modify them (including injecting credentials), then forwards to the real API.

239 

240**Option 2: HTTP\_PROXY / HTTPS\_PROXY (system-wide)**

241 

242```bash theme={null}

243export HTTP_PROXY="http://localhost:8080"

244export HTTPS_PROXY="http://localhost:8080"

245```

246 

247Claude Code and the Agent SDK respect these standard environment variables, routing all HTTP traffic through the proxy. For HTTPS, the proxy creates an encrypted CONNECT tunnel: it cannot see or modify request contents without TLS interception.

248 

249### Implementing a proxy

250 

251You can build your own proxy or use an existing one:

252 

253* [Envoy Proxy](https://www.envoyproxy.io/): production-grade proxy with `credential_injector` filter for adding auth headers

254* [mitmproxy](https://mitmproxy.org/): TLS-terminating proxy for inspecting and modifying HTTPS traffic

255* [Squid](http://www.squid-cache.org/): caching proxy with access control lists

256* [LiteLLM](https://github.com/BerriAI/litellm): LLM gateway with credential injection and rate limiting

257 

258### Credentials for other services

259 

260Beyond sampling from the Claude API, agents often need authenticated access to other services, such as git repositories, databases, and internal APIs. There are two main approaches:

261 

262#### Custom tools

263 

264Provide access through an MCP server or custom tool that routes requests to a service running outside the agent's security boundary. The agent calls the tool, but the actual authenticated request happens outside. The tool calls to a proxy which injects the credentials.

265 

266For example, a git MCP server could accept commands from the agent but forward them to a git proxy running on the host, which adds authentication before contacting the remote repository. The agent never sees the credentials.

267 

268Advantages:

269 

270* **No TLS interception**: The external service makes authenticated requests directly

271* **Credentials stay outside**: The agent only sees the tool interface, not the underlying credentials

272 

273#### Traffic forwarding

274 

275For Claude API calls, `ANTHROPIC_BASE_URL` lets you route requests to a proxy that can inspect and modify them in plaintext. But for other HTTPS services (GitHub, npm registries, internal APIs), the traffic is often encrypted end-to-end. Even if you route it through a proxy via `HTTP_PROXY`, the proxy only sees an opaque TLS tunnel and can't inject credentials.

276 

277To modify HTTPS traffic to arbitrary services, without using a custom tool, you need a TLS-terminating proxy that decrypts traffic, inspects or modifies it, then re-encrypts it before forwarding. This requires:

278 

2791. Running the proxy outside the agent's container

2802. Installing the proxy's CA certificate in the agent's trust store (so the agent trusts the proxy's certificates)

2813. Configuring `HTTP_PROXY`/`HTTPS_PROXY` to route traffic through the proxy

282 

283This approach handles any HTTP-based service without writing custom tools, but adds complexity around certificate management.

284 

285Note that not all programs respect `HTTP_PROXY`/`HTTPS_PROXY`. Most tools (curl, pip, npm, git) do, but some may bypass these variables and connect directly. For example, Node.js `fetch()` ignores these variables by default; in Node 24+ you can set `NODE_USE_ENV_PROXY=1` to enable support. For comprehensive coverage, you can use [proxychains](https://github.com/haad/proxychains) to intercept network calls, or configure iptables to redirect outbound traffic to a transparent proxy.

286 

287<Info>

288 A **transparent proxy** intercepts traffic at the network level, so the client doesn't need to be configured to use it. Regular proxies require clients to explicitly connect and speak HTTP CONNECT or SOCKS. Transparent proxies (like Squid or mitmproxy in transparent mode) can handle raw redirected TCP connections.

289</Info>

290 

291Both approaches still require the TLS-terminating proxy and trusted CA certificate. They just ensure traffic actually reaches the proxy.

292 

293## Filesystem configuration

294 

295Filesystem controls determine what files the agent can read and write.

296 

297### Read-only code mounting

298 

299When the agent needs to analyze code but not modify it, mount the directory read-only:

300 

301```bash theme={null}

302docker run -v /path/to/code:/workspace:ro agent-image

303```

304 

305<Warning>

306 Even read-only access to a code directory can expose credentials. Common files to exclude or sanitize before mounting:

307 

308 | File | Risk |

309 | ------------------------------------------------------- | ------------------------------------- |

310 | `.env`, `.env.local` | API keys, database passwords, secrets |

311 | `~/.git-credentials` | Git passwords/tokens in plaintext |

312 | `~/.aws/credentials` | AWS access keys |

313 | `~/.config/gcloud/application_default_credentials.json` | Google Cloud ADC tokens |

314 | `~/.azure/` | Azure CLI credentials |

315 | `~/.docker/config.json` | Docker registry auth tokens |

316 | `~/.kube/config` | Kubernetes cluster credentials |

317 | `.npmrc`, `.pypirc` | Package registry tokens |

318 | `*-service-account.json` | GCP service account keys |

319 | `*.pem`, `*.key` | Private keys |

320 

321 Consider copying only the source files needed, or using `.dockerignore`-style filtering.

322</Warning>

323 

324### Writable locations

325 

326If the agent needs to write files, you have a few options depending on whether you want changes to persist:

327 

328For ephemeral workspaces in containers, use `tmpfs` mounts that exist only in memory and are cleared when the container stops:

329 

330```bash theme={null}

331docker run \

332 --read-only \

333 --tmpfs /tmp:rw,noexec,nosuid,size=100m \

334 --tmpfs /workspace:rw,noexec,size=500m \

335 agent-image

336```

337 

338If you want to review changes before persisting them, an overlay filesystem lets the agent write without modifying underlying files. Changes are stored in a separate layer you can inspect, apply, or discard. For fully persistent output, mount a dedicated volume but keep it separate from sensitive directories.

339 

340## Further reading

341 

342* [Claude Code security documentation](/en/security)

343* [Hosting the Agent SDK](/en/agent-sdk/hosting)

344* [Handling permissions](/en/agent-sdk/permissions)

345* [Sandbox runtime](https://github.com/anthropic-experimental/sandbox-runtime)

346* [The Lethal Trifecta for AI Agents](https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/)

347* [OWASP Top 10 for LLM Applications](https://owasp.org/www-project-top-10-for-large-language-model-applications/)

348* [Docker Security Best Practices](https://docs.docker.com/engine/security/)

349* [gVisor Documentation](https://gvisor.dev/docs/)

350* [Firecracker Documentation](https://firecracker-microvm.github.io/)

agent-sdk/sessions.md +324 −0 added

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# Work with sessions

6 

7> How sessions persist agent conversation history, and when to use continue, resume, and fork to return to a prior run.

8 

9A session is the conversation history the SDK accumulates while your agent works. It contains your prompt, every tool call the agent made, every tool result, and every response. The SDK writes it to disk automatically so you can return to it later.

10 

11Returning to a session means the agent has full context from before: files it already read, analysis it already performed, decisions it already made. You can ask a follow-up question, recover from an interruption, or branch off to try a different approach.

12 

13<Note>

14 Sessions persist the **conversation**, not the filesystem. To snapshot and revert file changes the agent made, use [file checkpointing](/en/agent-sdk/file-checkpointing).

15</Note>

16 

17This guide covers how to pick the right approach for your app, the SDK interfaces that track sessions automatically, how to capture session IDs and use `resume` and `fork` manually, and what to know about resuming sessions across hosts.

18 

19## Choose an approach

20 

21How much session handling you need depends on your application's shape. Session management comes into play when you send multiple prompts that should share context. Within a single `query()` call, the agent already takes as many turns as it needs, and permission prompts and `AskUserQuestion` are [handled in-loop](/en/agent-sdk/user-input) (they don't end the call).

22 

23| What you're building | What to use |

24| :-------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |

25| One-shot task: single prompt, no follow-up | Nothing extra. One `query()` call handles it. |

26| Multi-turn chat in one process | [`ClaudeSDKClient` (Python) or `continue: true` (TypeScript)](#automatic-session-management). The SDK tracks the session for you with no ID handling. |

27| Pick up where you left off after a process restart | `continue_conversation=True` (Python) / `continue: true` (TypeScript). Resumes the most recent session in the directory, no ID needed. |

28| Resume a specific past session (not the most recent) | Capture the session ID and pass it to `resume`. |

29| Try an alternative approach without losing the original | Fork the session. |

30| Stateless task, don't want anything written to disk (TypeScript only) | Set [`persistSession: false`](/en/agent-sdk/typescript#options). The session exists only in memory for the duration of the call. Python always persists to disk. |

31 

32### Continue, resume, and fork

33 

34Continue, resume, and fork are option fields you set on `query()` ([`ClaudeAgentOptions`](/en/agent-sdk/python#claude-agent-options) in Python, [`Options`](/en/agent-sdk/typescript#options) in TypeScript).

35 

36**Continue** and **resume** both pick up an existing session and add to it. The difference is how they find that session:

37 

38* **Continue** finds the most recent session in the current directory. You don't track anything. Works well when your app runs one conversation at a time.

39* **Resume** takes a specific session ID. You track the ID. Required when you have multiple sessions (for example, one per user in a multi-user app) or want to return to one that isn't the most recent.

40 

41**Fork** is different: it creates a new session that starts with a copy of the original's history. The original stays unchanged. Use fork to try a different direction while keeping the option to go back.

42 

43## Automatic session management

44 

45Both SDKs offer an interface that tracks session state for you across calls, so you don't pass IDs around manually. Use these for multi-turn conversations within a single process.

46 

47### Python: `ClaudeSDKClient`

48 

49[`ClaudeSDKClient`](/en/agent-sdk/python#claude-sdk-client) handles session IDs internally. Each call to `client.query()` automatically continues the same session. Call [`client.receive_response()`](/en/agent-sdk/python#claude-sdk-client) to iterate over the messages for the current query. The client must be used as an async context manager.

50 

51This example runs two queries against the same `client`. The first asks the agent to analyze a module; the second asks it to refactor that module. Because both calls go through the same client instance, the second query has full context from the first without any explicit `resume` or session ID:

52 

53```python Python theme={null}

54import asyncio

55from claude_agent_sdk import (

56 ClaudeSDKClient,

57 ClaudeAgentOptions,

58 AssistantMessage,

59 ResultMessage,

60 TextBlock,

61)

62 

63 

64def print_response(message):

65 """Print only the human-readable parts of a message."""

66 if isinstance(message, AssistantMessage):

67 for block in message.content:

68 if isinstance(block, TextBlock):

69 print(block.text)

70 elif isinstance(message, ResultMessage):

71 cost = (

72 f"${message.total_cost_usd:.4f}"

73 if message.total_cost_usd is not None

74 else "N/A"

75 )

76 print(f"[done: {message.subtype}, cost: {cost}]")

77 

78 

79async def main():

80 options = ClaudeAgentOptions(

81 allowed_tools=["Read", "Edit", "Glob", "Grep"],

82 )

83 

84 async with ClaudeSDKClient(options=options) as client:

85 # First query: client captures the session ID internally

86 await client.query("Analyze the auth module")

87 async for message in client.receive_response():

88 print_response(message)

89 

90 # Second query: automatically continues the same session

91 await client.query("Now refactor it to use JWT")

92 async for message in client.receive_response():

93 print_response(message)

94 

95 

96asyncio.run(main())

97```

98 

99See the [Python SDK reference](/en/agent-sdk/python#choosing-between-query-and-claude-sdk-client) for details on when to use `ClaudeSDKClient` vs the standalone `query()` function.

100 

101### TypeScript: `continue: true`

102 

103The stable TypeScript SDK (the `query()` function used throughout these docs, sometimes called V1) doesn't have a session-holding client object like Python's `ClaudeSDKClient`. Instead, pass `continue: true` on each subsequent `query()` call and the SDK picks up the most recent session in the current directory. No ID tracking required.

104 

105This example makes two separate `query()` calls. The first creates a fresh session; the second sets `continue: true`, which tells the SDK to find and resume the most recent session on disk. The agent has full context from the first call:

106 

107```typescript TypeScript theme={null}

108import { query } from "@anthropic-ai/claude-agent-sdk";

109 

110// First query: creates a new session

111for await (const message of query({

112 prompt: "Analyze the auth module",

113 options: { allowedTools: ["Read", "Glob", "Grep"] }

114})) {

115 if (message.type === "result" && message.subtype === "success") {

116 console.log(message.result);

117 }

118}

119 

120// Second query: continue: true resumes the most recent session

121for await (const message of query({

122 prompt: "Now refactor it to use JWT",

123 options: {

124 continue: true,

125 allowedTools: ["Read", "Edit", "Write", "Glob", "Grep"]

126 }

127})) {

128 if (message.type === "result" && message.subtype === "success") {

129 console.log(message.result);

130 }

131}

132```

133 

134<Note>

135 There's also a [V2 preview](/en/agent-sdk/typescript-v2-preview) of the TypeScript SDK that provides `createSession()` with a `send` / `stream` pattern, closer to Python's `ClaudeSDKClient` in feel. V2 is unstable and its APIs may change; the rest of this documentation uses the stable V1 `query()` function.

136</Note>

137 

138## Use session options with `query()`

139 

140### Capture the session ID

141 

142Resume and fork require a session ID. Read it from the `session_id` field on the result message ([`ResultMessage`](/en/agent-sdk/python#result-message) in Python, [`SDKResultMessage`](/en/agent-sdk/typescript#sdk-result-message) in TypeScript), which is present on every result regardless of success or error. In TypeScript the ID is also available earlier as a direct field on the init `SystemMessage`; in Python it's nested inside `SystemMessage.data`.

143 

144<CodeGroup>

145 ```python Python theme={null}

146 import asyncio

147 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

148 

149 

150 async def main():

151 session_id = None

152 

153 async for message in query(

154 prompt="Analyze the auth module and suggest improvements",

155 options=ClaudeAgentOptions(

156 allowed_tools=["Read", "Glob", "Grep"],

157 ),

158 ):

159 if isinstance(message, ResultMessage):

160 session_id = message.session_id

161 if message.subtype == "success":

162 print(message.result)

163 

164 print(f"Session ID: {session_id}")

165 return session_id

166 

167 

168 session_id = asyncio.run(main())

169 ```

170 

171 ```typescript TypeScript theme={null}

172 import { query } from "@anthropic-ai/claude-agent-sdk";

173 

174 let sessionId: string | undefined;

175 

176 for await (const message of query({

177 prompt: "Analyze the auth module and suggest improvements",

178 options: { allowedTools: ["Read", "Glob", "Grep"] }

179 })) {

180 if (message.type === "result") {

181 sessionId = message.session_id;

182 if (message.subtype === "success") {

183 console.log(message.result);

184 }

185 }

186 }

187 

188 console.log(`Session ID: ${sessionId}`);

189 ```

190</CodeGroup>

191 

192### Resume by ID

193 

194Pass a session ID to `resume` to return to that specific session. The agent picks up with full context from wherever the session left off. Common reasons to resume:

195 

196* **Follow up on a completed task.** The agent already analyzed something; now you want it to act on that analysis without re-reading files.

197* **Recover from a limit.** The first run ended with `error_max_turns` or `error_max_budget_usd` (see [Handle the result](/en/agent-sdk/agent-loop#handle-the-result)); resume with a higher limit.

198* **Restart your process.** You captured the ID before shutdown and want to restore the conversation.

199 

200This example resumes the session from [Capture the session ID](#capture-the-session-id) with a follow-up prompt. Because you're resuming, the agent already has the prior analysis in context:

201 

202<CodeGroup>

203 ```python Python theme={null}

204 # Earlier session analyzed the code; now build on that analysis

205 async for message in query(

206 prompt="Now implement the refactoring you suggested",

207 options=ClaudeAgentOptions(

208 resume=session_id,

209 allowed_tools=["Read", "Edit", "Write", "Glob", "Grep"],

210 ),

211 ):

212 if isinstance(message, ResultMessage) and message.subtype == "success":

213 print(message.result)

214 ```

215 

216 ```typescript TypeScript theme={null}

217 // Earlier session analyzed the code; now build on that analysis

218 for await (const message of query({

219 prompt: "Now implement the refactoring you suggested",

220 options: {

221 resume: sessionId,

222 allowedTools: ["Read", "Edit", "Write", "Glob", "Grep"]

223 }

224 })) {

225 if (message.type === "result" && message.subtype === "success") {

226 console.log(message.result);

227 }

228 }

229 ```

230</CodeGroup>

231 

232<Tip>

233 If a `resume` call returns a fresh session instead of the expected history, the most common cause is a mismatched `cwd`. Sessions are stored under `~/.claude/projects/<encoded-cwd>/*.jsonl`, where `<encoded-cwd>` is the absolute working directory with every non-alphanumeric character replaced by `-` (so `/Users/me/proj` becomes `-Users-me-proj`). If your resume call runs from a different directory, the SDK looks in the wrong place. The session file also needs to exist on the current machine.

234</Tip>

235 

236To resume sessions across machines or in serverless environments, mirror transcripts to shared storage with a [`SessionStore` adapter](/en/agent-sdk/session-storage).

237 

238### Fork to explore alternatives

239 

240Forking creates a new session that starts with a copy of the original's history but diverges from that point. The fork gets its own session ID; the original's ID and history stay unchanged. You end up with two independent sessions you can resume separately.

241 

242<Note>

243 Forking branches the conversation history, not the filesystem. If a forked agent edits files, those changes are real and visible to any session working in the same directory. To branch and revert file changes, use [file checkpointing](/en/agent-sdk/file-checkpointing).

244</Note>

245 

246This example builds on [Capture the session ID](#capture-the-session-id): you've already analyzed an auth module in `session_id` and want to explore OAuth2 without losing the JWT-focused thread. The first block forks the session and captures the fork's ID (`forked_id`); the second block resumes the original `session_id` to continue down the JWT path. You now have two session IDs pointing at two separate histories:

247 

248<CodeGroup>

249 ```python Python theme={null}

250 # Fork: branch from session_id into a new session

251 forked_id = None

252 async for message in query(

253 prompt="Instead of JWT, implement OAuth2 for the auth module",

254 options=ClaudeAgentOptions(

255 resume=session_id,

256 fork_session=True,

257 ),

258 ):

259 if isinstance(message, ResultMessage):

260 forked_id = message.session_id # The fork's ID, distinct from session_id

261 if message.subtype == "success":

262 print(message.result)

263 

264 print(f"Forked session: {forked_id}")

265 

266 # Original session is untouched; resuming it continues the JWT thread

267 async for message in query(

268 prompt="Continue with the JWT approach",

269 options=ClaudeAgentOptions(resume=session_id),

270 ):

271 if isinstance(message, ResultMessage) and message.subtype == "success":

272 print(message.result)

273 ```

274 

275 ```typescript TypeScript theme={null}

276 // Fork: branch from sessionId into a new session

277 let forkedId: string | undefined;

278 

279 for await (const message of query({

280 prompt: "Instead of JWT, implement OAuth2 for the auth module",

281 options: {

282 resume: sessionId,

283 forkSession: true

284 }

285 })) {

286 if (message.type === "system" && message.subtype === "init") {

287 forkedId = message.session_id; // The fork's ID, distinct from sessionId

288 }

289 if (message.type === "result" && message.subtype === "success") {

290 console.log(message.result);

291 }

292 }

293 

294 console.log(`Forked session: ${forkedId}`);

295 

296 // Original session is untouched; resuming it continues the JWT thread

297 for await (const message of query({

298 prompt: "Continue with the JWT approach",

299 options: { resume: sessionId }

300 })) {

301 if (message.type === "result" && message.subtype === "success") {

302 console.log(message.result);

303 }

304 }

305 ```

306</CodeGroup>

307 

308## Resume across hosts

309 

310Session files are local to the machine that created them. To resume a session on a different host (CI workers, ephemeral containers, serverless), you have two options:

311 

312* **Move the session file.** Persist `~/.claude/projects/<encoded-cwd>/<session-id>.jsonl` from the first run and restore it to the same path on the new host before calling `resume`. The `cwd` must match.

313* **Don't rely on session resume.** Capture the results you need (analysis output, decisions, file diffs) as application state and pass them into a fresh session's prompt. This is often more robust than shipping transcript files around.

314 

315Both SDKs expose functions for enumerating sessions on disk and reading their messages: [`listSessions()`](/en/agent-sdk/typescript#list-sessions) and [`getSessionMessages()`](/en/agent-sdk/typescript#get-session-messages) in TypeScript, [`list_sessions()`](/en/agent-sdk/python#list-sessions) and [`get_session_messages()`](/en/agent-sdk/python#get-session-messages) in Python. Use them to build custom session pickers, cleanup logic, or transcript viewers.

316 

317Both SDKs also expose functions for looking up and mutating individual sessions: [`get_session_info()`](/en/agent-sdk/python#get-session-info), [`rename_session()`](/en/agent-sdk/python#rename-session), and [`tag_session()`](/en/agent-sdk/python#tag-session) in Python, and [`getSessionInfo()`](/en/agent-sdk/typescript#get-session-info), [`renameSession()`](/en/agent-sdk/typescript#rename-session), and [`tagSession()`](/en/agent-sdk/typescript#tag-session) in TypeScript. Use them to organize sessions by tag or give them human-readable titles.

318 

319## Related resources

320 

321* [How the agent loop works](/en/agent-sdk/agent-loop): Understand turns, messages, and context accumulation within a session

322* [File checkpointing](/en/agent-sdk/file-checkpointing): Track and revert file changes across sessions

323* [Python `ClaudeAgentOptions`](/en/agent-sdk/python#claude-agent-options): Full session option reference for Python

324* [TypeScript `Options`](/en/agent-sdk/typescript#options): Full session option reference for TypeScript

agent-sdk/skills.md +297 −0 added

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# Agent Skills in the SDK

6 

7> Extend Claude with specialized capabilities using Agent Skills in the Claude Agent SDK

8 

9## Overview

10 

11Agent Skills extend Claude with specialized capabilities that Claude autonomously invokes when relevant. Skills are packaged as `SKILL.md` files containing instructions, descriptions, and optional supporting resources.

12 

13For comprehensive information about Skills, including benefits, architecture, and authoring guidelines, see the [Agent Skills overview](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview).

14 

15## How Skills Work with the SDK

16 

17When using the Claude Agent SDK, Skills are:

18 

191. **Defined as filesystem artifacts**: Created as `SKILL.md` files in specific directories (`.claude/skills/`)

202. **Loaded from filesystem**: Skills are loaded from filesystem locations governed by `settingSources` (TypeScript) or `setting_sources` (Python)

213. **Automatically discovered**: Once filesystem settings are loaded, Skill metadata is discovered at startup from user and project directories; full content loaded when triggered

224. **Model-invoked**: Claude autonomously chooses when to use them based on context

235. **Enabled via allowed\_tools**: Add `"Skill"` to your `allowed_tools` to enable Skills

24 

25Unlike subagents (which can be defined programmatically), Skills must be created as filesystem artifacts. The SDK does not provide a programmatic API for registering Skills.

26 

27<Note>

28 Skills are discovered through the filesystem setting sources. With default `query()` options, the SDK loads user and project sources, so skills in `~/.claude/skills/` and `<cwd>/.claude/skills/` are available. If you set `settingSources` explicitly, include `'user'` or `'project'` to keep skill discovery, or use the [`plugins` option](/en/agent-sdk/plugins) to load skills from a specific path.

29</Note>

30 

31## Using Skills with the SDK

32 

33To use Skills with the SDK, you need to:

34 

351. Include `"Skill"` in your `allowed_tools` configuration

362. Configure `settingSources`/`setting_sources` to load Skills from the filesystem

37 

38Once configured, Claude automatically discovers Skills from the specified directories and invokes them when relevant to the user's request.

39 

40<CodeGroup>

41 ```python Python theme={null}

42 import asyncio

43 from claude_agent_sdk import query, ClaudeAgentOptions

44 

45 

46 async def main():

47 options = ClaudeAgentOptions(

48 cwd="/path/to/project", # Project with .claude/skills/

49 setting_sources=["user", "project"], # Load Skills from filesystem

50 allowed_tools=["Skill", "Read", "Write", "Bash"], # Enable Skill tool

51 )

52 

53 async for message in query(

54 prompt="Help me process this PDF document", options=options

55 ):

56 print(message)

57 

58 

59 asyncio.run(main())

60 ```

61 

62 ```typescript TypeScript theme={null}

63 import { query } from "@anthropic-ai/claude-agent-sdk";

64 

65 for await (const message of query({

66 prompt: "Help me process this PDF document",

67 options: {

68 cwd: "/path/to/project", // Project with .claude/skills/

69 settingSources: ["user", "project"], // Load Skills from filesystem

70 allowedTools: ["Skill", "Read", "Write", "Bash"] // Enable Skill tool

71 }

72 })) {

73 console.log(message);

74 }

75 ```

76</CodeGroup>

77 

78## Skill Locations

79 

80Skills are loaded from filesystem directories based on your `settingSources`/`setting_sources` configuration:

81 

82* **Project Skills** (`.claude/skills/`): Shared with your team via git - loaded when `setting_sources` includes `"project"`

83* **User Skills** (`~/.claude/skills/`): Personal Skills across all projects - loaded when `setting_sources` includes `"user"`

84* **Plugin Skills**: Bundled with installed Claude Code plugins

85 

86## Creating Skills

87 

88Skills are defined as directories containing a `SKILL.md` file with YAML frontmatter and Markdown content. The `description` field determines when Claude invokes your Skill.

89 

90**Example directory structure**:

91 

92```bash theme={null}

93.claude/skills/processing-pdfs/

94└── SKILL.md

95```

96 

97For complete guidance on creating Skills, including SKILL.md structure, multi-file Skills, and examples, see:

98 

99* [Agent Skills in Claude Code](/en/skills): Complete guide with examples

100* [Agent Skills Best Practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices): Authoring guidelines and naming conventions

101 

102## Tool Restrictions

103 

104<Note>

105 The `allowed-tools` frontmatter field in SKILL.md is only supported when using Claude Code CLI directly. **It does not apply when using Skills through the SDK**.

106 

107 When using the SDK, control tool access through the main `allowedTools` option in your query configuration.

108</Note>

109 

110To control tool access for Skills in SDK applications, use `allowedTools` to pre-approve specific tools. Without a `canUseTool` callback, anything not in the list is denied:

111 

112<Note>

113 Import statements from the first example are assumed in the following code snippets.

114</Note>

115 

116<CodeGroup>

117 ```python Python theme={null}

118 options = ClaudeAgentOptions(

119 setting_sources=["user", "project"], # Load Skills from filesystem

120 allowed_tools=["Skill", "Read", "Grep", "Glob"],

121 )

122 

123 async for message in query(prompt="Analyze the codebase structure", options=options):

124 print(message)

125 ```

126 

127 ```typescript TypeScript theme={null}

128 for await (const message of query({

129 prompt: "Analyze the codebase structure",

130 options: {

131 settingSources: ["user", "project"], // Load Skills from filesystem

132 allowedTools: ["Skill", "Read", "Grep", "Glob"],

133 permissionMode: "dontAsk" // Deny anything not in allowedTools

134 }

135 })) {

136 console.log(message);

137 }

138 ```

139</CodeGroup>

140 

141## Discovering Available Skills

142 

143To see which Skills are available in your SDK application, simply ask Claude:

144 

145<CodeGroup>

146 ```python Python theme={null}

147 options = ClaudeAgentOptions(

148 setting_sources=["user", "project"], # Load Skills from filesystem

149 allowed_tools=["Skill"],

150 )

151 

152 async for message in query(prompt="What Skills are available?", options=options):

153 print(message)

154 ```

155 

156 ```typescript TypeScript theme={null}

157 for await (const message of query({

158 prompt: "What Skills are available?",

159 options: {

160 settingSources: ["user", "project"], // Load Skills from filesystem

161 allowedTools: ["Skill"]

162 }

163 })) {

164 console.log(message);

165 }

166 ```

167</CodeGroup>

168 

169Claude will list the available Skills based on your current working directory and installed plugins.

170 

171## Testing Skills

172 

173Test Skills by asking questions that match their descriptions:

174 

175<CodeGroup>

176 ```python Python theme={null}

177 options = ClaudeAgentOptions(

178 cwd="/path/to/project",

179 setting_sources=["user", "project"], # Load Skills from filesystem

180 allowed_tools=["Skill", "Read", "Bash"],

181 )

182 

183 async for message in query(prompt="Extract text from invoice.pdf", options=options):

184 print(message)

185 ```

186 

187 ```typescript TypeScript theme={null}

188 for await (const message of query({

189 prompt: "Extract text from invoice.pdf",

190 options: {

191 cwd: "/path/to/project",

192 settingSources: ["user", "project"], // Load Skills from filesystem

193 allowedTools: ["Skill", "Read", "Bash"]

194 }

195 })) {

196 console.log(message);

197 }

198 ```

199</CodeGroup>

200 

201Claude automatically invokes the relevant Skill if the description matches your request.

202 

203## Troubleshooting

204 

205### Skills Not Found

206 

207**Check settingSources configuration**: Skills are discovered through the `user` and `project` setting sources. If you set `settingSources`/`setting_sources` explicitly and omit those sources, skills are not loaded:

208 

209<CodeGroup>

210 ```python Python theme={null}

211 # Skills not loaded: setting_sources excludes user and project

212 options = ClaudeAgentOptions(setting_sources=[], allowed_tools=["Skill"])

213 

214 # Skills loaded: user and project sources included

215 options = ClaudeAgentOptions(

216 setting_sources=["user", "project"],

217 allowed_tools=["Skill"],

218 )

219 ```

220 

221 ```typescript TypeScript theme={null}

222 // Skills not loaded: settingSources excludes user and project

223 const options = {

224 settingSources: [],

225 allowedTools: ["Skill"]

226 };

227 

228 // Skills loaded: user and project sources included

229 const options = {

230 settingSources: ["user", "project"],

231 allowedTools: ["Skill"]

232 };

233 ```

234</CodeGroup>

235 

236For more details on `settingSources`/`setting_sources`, see the [TypeScript SDK reference](/en/agent-sdk/typescript#setting-source) or [Python SDK reference](/en/agent-sdk/python#setting-source).

237 

238**Check working directory**: The SDK loads Skills relative to the `cwd` option. Ensure it points to a directory containing `.claude/skills/`:

239 

240<CodeGroup>

241 ```python Python theme={null}

242 # Ensure your cwd points to the directory containing .claude/skills/

243 options = ClaudeAgentOptions(

244 cwd="/path/to/project", # Must contain .claude/skills/

245 setting_sources=["user", "project"], # Loads skills from these sources

246 allowed_tools=["Skill"],

247 )

248 ```

249 

250 ```typescript TypeScript theme={null}

251 // Ensure your cwd points to the directory containing .claude/skills/

252 const options = {

253 cwd: "/path/to/project", // Must contain .claude/skills/

254 settingSources: ["user", "project"], // Loads skills from these sources

255 allowedTools: ["Skill"]

256 };

257 ```

258</CodeGroup>

259 

260See the "Using Skills with the SDK" section above for the complete pattern.

261 

262**Verify filesystem location**:

263 

264```bash theme={null}

265# Check project Skills

266ls .claude/skills/*/SKILL.md

267 

268# Check personal Skills

269ls ~/.claude/skills/*/SKILL.md

270```

271 

272### Skill Not Being Used

273 

274**Check the Skill tool is enabled**: Confirm `"Skill"` is in your `allowedTools`.

275 

276**Check the description**: Ensure it's specific and includes relevant keywords. See [Agent Skills Best Practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#writing-effective-descriptions) for guidance on writing effective descriptions.

277 

278### Additional Troubleshooting

279 

280For general Skills troubleshooting (YAML syntax, debugging, etc.), see the [Claude Code Skills troubleshooting section](/en/skills#troubleshooting).

281 

282## Related Documentation

283 

284### Skills Guides

285 

286* [Agent Skills in Claude Code](/en/skills): Complete Skills guide with creation, examples, and troubleshooting

287* [Agent Skills Overview](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview): Conceptual overview, benefits, and architecture

288* [Agent Skills Best Practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices): Authoring guidelines for effective Skills

289* [Agent Skills Cookbook](https://platform.claude.com/cookbook/skills-notebooks-01-skills-introduction): Example Skills and templates

290 

291### SDK Resources

292 

293* [Subagents in the SDK](/en/agent-sdk/subagents): Similar filesystem-based agents with programmatic options

294* [Slash Commands in the SDK](/en/agent-sdk/slash-commands): User-invoked commands

295* [SDK Overview](/en/agent-sdk/overview): General SDK concepts

296* [TypeScript SDK Reference](/en/agent-sdk/typescript): Complete API documentation

297* [Python SDK Reference](/en/agent-sdk/python): Complete API documentation

agent-sdk/slash-commands.md +444 −0 added

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# Slash Commands in the SDK

6 

7> Learn how to use slash commands to control Claude Code sessions through the SDK

8 

9Slash commands provide a way to control Claude Code sessions with special commands that start with `/`. These commands can be sent through the SDK to perform actions like compacting context, listing context usage, or invoking custom commands. Only commands that work without an interactive terminal are dispatchable through the SDK; the `system/init` message lists the ones available in your session.

10 

11## Discovering Available Slash Commands

12 

13The Claude Agent SDK provides information about available slash commands in the system initialization message. Access this information when your session starts:

14 

15<CodeGroup>

16 ```typescript TypeScript theme={null}

17 import { query } from "@anthropic-ai/claude-agent-sdk";

18 

19 for await (const message of query({

20 prompt: "Hello Claude",

21 options: { maxTurns: 1 }

22 })) {

23 if (message.type === "system" && message.subtype === "init") {

24 console.log("Available slash commands:", message.slash_commands);

25 // Example output: ["/compact", "/context", "/usage"]

26 }

27 }

28 ```

29 

30 ```python Python theme={null}

31 import asyncio

32 from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage

33 

34 

35 async def main():

36 async for message in query(prompt="Hello Claude", options=ClaudeAgentOptions(max_turns=1)):

37 if isinstance(message, SystemMessage) and message.subtype == "init":

38 print("Available slash commands:", message.data["slash_commands"])

39 # Example output: ["/compact", "/context", "/usage"]

40 

41 

42 asyncio.run(main())

43 ```

44</CodeGroup>

45 

46## Sending Slash Commands

47 

48Send slash commands by including them in your prompt string, just like regular text:

49 

50<CodeGroup>

51 ```typescript TypeScript theme={null}

52 import { query } from "@anthropic-ai/claude-agent-sdk";

53 

54 // Send a slash command

55 for await (const message of query({

56 prompt: "/compact",

57 options: { maxTurns: 1 }

58 })) {

59 if (message.type === "result") {

60 console.log("Command executed:", message.result);

61 }

62 }

63 ```

64 

65 ```python Python theme={null}

66 import asyncio

67 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

68 

69 

70 async def main():

71 # Send a slash command

72 async for message in query(prompt="/compact", options=ClaudeAgentOptions(max_turns=1)):

73 if isinstance(message, ResultMessage):

74 print("Command executed:", message.result)

75 

76 

77 asyncio.run(main())

78 ```

79</CodeGroup>

80 

81## Common Slash Commands

82 

83### `/compact` - Compact Conversation History

84 

85The `/compact` command reduces the size of your conversation history by summarizing older messages while preserving important context:

86 

87<CodeGroup>

88 ```typescript TypeScript theme={null}

89 import { query } from "@anthropic-ai/claude-agent-sdk";

90 

91 for await (const message of query({

92 prompt: "/compact",

93 options: { maxTurns: 1 }

94 })) {

95 if (message.type === "system" && message.subtype === "compact_boundary") {

96 console.log("Compaction completed");

97 console.log("Pre-compaction tokens:", message.compact_metadata.pre_tokens);

98 console.log("Trigger:", message.compact_metadata.trigger);

99 }

100 }

101 ```

102 

103 ```python Python theme={null}

104 import asyncio

105 from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage

106 

107 

108 async def main():

109 async for message in query(prompt="/compact", options=ClaudeAgentOptions(max_turns=1)):

110 if isinstance(message, SystemMessage) and message.subtype == "compact_boundary":

111 print("Compaction completed")

112 print("Pre-compaction tokens:", message.data["compact_metadata"]["pre_tokens"])

113 print("Trigger:", message.data["compact_metadata"]["trigger"])

114 

115 

116 asyncio.run(main())

117 ```

118</CodeGroup>

119 

120### Clearing the conversation

121 

122The interactive `/clear` command is not available in the SDK. Each `query()` call already starts a fresh conversation, so to clear context, end the current `query()` and start a new one. The previous conversation stays on disk and can be returned to by passing its session ID to the [`resume` option](/en/agent-sdk/sessions#resume-by-id).

123 

124## Creating Custom Slash Commands

125 

126In addition to using built-in slash commands, you can create your own custom commands that are available through the SDK. Custom commands are defined as markdown files in specific directories, similar to how subagents are configured.

127 

128<Note>

129 The `.claude/commands/` directory is the legacy format. The recommended format is `.claude/skills/<name>/SKILL.md`, which supports the same slash-command invocation (`/name`) plus autonomous invocation by Claude. See [Skills](/en/agent-sdk/skills) for the current format. The CLI continues to support both formats, and the examples below remain accurate for `.claude/commands/`.

130</Note>

131 

132### File Locations

133 

134Custom slash commands are stored in designated directories based on their scope:

135 

136* **Project commands**: `.claude/commands/` - Available only in the current project (legacy; prefer `.claude/skills/`)

137* **Personal commands**: `~/.claude/commands/` - Available across all your projects (legacy; prefer `~/.claude/skills/`)

138 

139### File Format

140 

141Each custom command is a markdown file where:

142 

143* The filename (without `.md` extension) becomes the command name

144* The file content defines what the command does

145* Optional YAML frontmatter provides configuration

146 

147#### Basic Example

148 

149Create `.claude/commands/refactor.md`:

150 

151```markdown theme={null}

152Refactor the selected code to improve readability and maintainability.

153Focus on clean code principles and best practices.

154```

155 

156This creates the `/refactor` command that you can use through the SDK.

157 

158#### With Frontmatter

159 

160Create `.claude/commands/security-check.md`:

161 

162```markdown theme={null}

163---

164allowed-tools: Read, Grep, Glob

165description: Run security vulnerability scan

166model: claude-opus-4-7

167---

168 

169Analyze the codebase for security vulnerabilities including:

170- SQL injection risks

171- XSS vulnerabilities

172- Exposed credentials

173- Insecure configurations

174```

175 

176### Using Custom Commands in the SDK

177 

178Once defined in the filesystem, custom commands are automatically available through the SDK:

179 

180<CodeGroup>

181 ```typescript TypeScript theme={null}

182 import { query } from "@anthropic-ai/claude-agent-sdk";

183 

184 // Use a custom command

185 for await (const message of query({

186 prompt: "/refactor src/auth/login.ts",

187 options: { maxTurns: 3 }

188 })) {

189 if (message.type === "assistant") {

190 console.log("Refactoring suggestions:", message.message);

191 }

192 }

193 

194 // Custom commands appear in the slash_commands list

195 for await (const message of query({

196 prompt: "Hello",

197 options: { maxTurns: 1 }

198 })) {

199 if (message.type === "system" && message.subtype === "init") {

200 // Will include both built-in and custom commands

201 console.log("Available commands:", message.slash_commands);

202 // Example: ["/compact", "/context", "/usage", "/refactor", "/security-check"]

203 }

204 }

205 ```

206 

207 ```python Python theme={null}

208 import asyncio

209 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, SystemMessage

210 

211 

212 async def main():

213 # Use a custom command

214 async for message in query(

215 prompt="/refactor src/auth/login.py", options=ClaudeAgentOptions(max_turns=3)

216 ):

217 if isinstance(message, AssistantMessage):

218 for block in message.content:

219 if hasattr(block, "text"):

220 print("Refactoring suggestions:", block.text)

221 

222 # Custom commands appear in the slash_commands list

223 async for message in query(prompt="Hello", options=ClaudeAgentOptions(max_turns=1)):

224 if isinstance(message, SystemMessage) and message.subtype == "init":

225 # Will include both built-in and custom commands

226 print("Available commands:", message.data["slash_commands"])

227 # Example: ["/compact", "/context", "/usage", "/refactor", "/security-check"]

228 

229 

230 asyncio.run(main())

231 ```

232</CodeGroup>

233 

234### Advanced Features

235 

236#### Arguments and Placeholders

237 

238Custom commands support dynamic arguments using placeholders:

239 

240Create `.claude/commands/fix-issue.md`:

241 

242```markdown theme={null}

243---

244argument-hint: [issue-number] [priority]

245description: Fix a GitHub issue

246---

247 

248Fix issue #$1 with priority $2.

249Check the issue description and implement the necessary changes.

250```

251 

252Use in SDK:

253 

254<CodeGroup>

255 ```typescript TypeScript theme={null}

256 import { query } from "@anthropic-ai/claude-agent-sdk";

257 

258 // Pass arguments to custom command

259 for await (const message of query({

260 prompt: "/fix-issue 123 high",

261 options: { maxTurns: 5 }

262 })) {

263 // Command will process with $1="123" and $2="high"

264 if (message.type === "result") {

265 console.log("Issue fixed:", message.result);

266 }

267 }

268 ```

269 

270 ```python Python theme={null}

271 import asyncio

272 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

273 

274 

275 async def main():

276 # Pass arguments to custom command

277 async for message in query(prompt="/fix-issue 123 high", options=ClaudeAgentOptions(max_turns=5)):

278 # Command will process with $1="123" and $2="high"

279 if isinstance(message, ResultMessage):

280 print("Issue fixed:", message.result)

281 

282 

283 asyncio.run(main())

284 ```

285</CodeGroup>

286 

287#### Bash Command Execution

288 

289Custom commands can execute bash commands and include their output:

290 

291Create `.claude/commands/git-commit.md`:

292 

293```markdown theme={null}

294---

295allowed-tools: Bash(git add *), Bash(git status *), Bash(git commit *)

296description: Create a git commit

297---

298 

299## Context

300 

301- Current status: !`git status`

302- Current diff: !`git diff HEAD`

303 

304## Task

305 

306Create a git commit with appropriate message based on the changes.

307```

308 

309#### File References

310 

311Include file contents using the `@` prefix:

312 

313Create `.claude/commands/review-config.md`:

314 

315```markdown theme={null}

316---

317description: Review configuration files

318---

319 

320Review the following configuration files for issues:

321- Package config: @package.json

322- TypeScript config: @tsconfig.json

323- Environment config: @.env

324 

325Check for security issues, outdated dependencies, and misconfigurations.

326```

327 

328### Organization with Namespacing

329 

330Organize commands in subdirectories for better structure:

331 

332```bash theme={null}

333.claude/commands/

334├── frontend/

335│ ├── component.md # Creates /component (project:frontend)

336│ └── style-check.md # Creates /style-check (project:frontend)

337├── backend/

338│ ├── api-test.md # Creates /api-test (project:backend)

339│ └── db-migrate.md # Creates /db-migrate (project:backend)

340└── review.md # Creates /review (project)

341```

342 

343The subdirectory appears in the command description but doesn't affect the command name itself.

344 

345### Practical Examples

346 

347#### Code Review Command

348 

349Create `.claude/commands/code-review.md`:

350 

351```markdown theme={null}

352---

353allowed-tools: Read, Grep, Glob, Bash(git diff *)

354description: Comprehensive code review

355---

356 

357## Changed Files

358!`git diff --name-only HEAD~1`

359 

360## Detailed Changes

361!`git diff HEAD~1`

362 

363## Review Checklist

364 

365Review the above changes for:

3661. Code quality and readability

3672. Security vulnerabilities

3683. Performance implications

3694. Test coverage

3705. Documentation completeness

371 

372Provide specific, actionable feedback organized by priority.

373```

374 

375#### Test Runner Command

376 

377Create `.claude/commands/test.md`:

378 

379```markdown theme={null}

380---

381allowed-tools: Bash, Read, Edit

382argument-hint: [test-pattern]

383description: Run tests with optional pattern

384---

385 

386Run tests matching pattern: $ARGUMENTS

387 

3881. Detect the test framework (Jest, pytest, etc.)

3892. Run tests with the provided pattern

3903. If tests fail, analyze and fix them

3914. Re-run to verify fixes

392```

393 

394Use these commands through the SDK:

395 

396<CodeGroup>

397 ```typescript TypeScript theme={null}

398 import { query } from "@anthropic-ai/claude-agent-sdk";

399 

400 // Run code review

401 for await (const message of query({

402 prompt: "/code-review",

403 options: { maxTurns: 3 }

404 })) {

405 // Process review feedback

406 }

407 

408 // Run specific tests

409 for await (const message of query({

410 prompt: "/test auth",

411 options: { maxTurns: 5 }

412 })) {

413 // Handle test results

414 }

415 ```

416 

417 ```python Python theme={null}

418 import asyncio

419 from claude_agent_sdk import query, ClaudeAgentOptions

420 

421 

422 async def main():

423 # Run code review

424 async for message in query(prompt="/code-review", options=ClaudeAgentOptions(max_turns=3)):

425 # Process review feedback

426 pass

427 

428 # Run specific tests

429 async for message in query(prompt="/test auth", options=ClaudeAgentOptions(max_turns=5)):

430 # Handle test results

431 pass

432 

433 

434 asyncio.run(main())

435 ```

436</CodeGroup>

437 

438## See Also

439 

440* [Slash Commands](/en/skills) - Complete slash command documentation

441* [Subagents in the SDK](/en/agent-sdk/subagents) - Similar filesystem-based configuration for subagents

442* [TypeScript SDK reference](/en/agent-sdk/typescript) - Complete API documentation

443* [SDK overview](/en/agent-sdk/overview) - General SDK concepts

444* [CLI reference](/en/cli-reference) - Command-line interface

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# Stream responses in real-time

6 

7> Get real-time responses from the Agent SDK as text and tool calls stream in

8 

9By default, the Agent SDK yields complete `AssistantMessage` objects after Claude finishes generating each response. To receive incremental updates as text and tool calls are generated, enable partial message streaming by setting `include_partial_messages` (Python) or `includePartialMessages` (TypeScript) to `true` in your options.

10 

11<Tip>

12 This page covers output streaming (receiving tokens in real-time). For input modes (how you send messages), see [Send messages to agents](/en/agent-sdk/streaming-vs-single-mode). You can also [stream responses using the Agent SDK via the CLI](/en/headless).

13</Tip>

14 

15## Enable streaming output

16 

17To enable streaming, set `include_partial_messages` (Python) or `includePartialMessages` (TypeScript) to `true` in your options. This causes the SDK to yield `StreamEvent` messages containing raw API events as they arrive, in addition to the usual `AssistantMessage` and `ResultMessage`.

18 

19Your code then needs to:

20 

211. Check each message's type to distinguish `StreamEvent` from other message types

222. For `StreamEvent`, extract the `event` field and check its `type`

233. Look for `content_block_delta` events where `delta.type` is `text_delta`, which contain the actual text chunks

24 

25The example below enables streaming and prints text chunks as they arrive. Notice the nested type checks: first for `StreamEvent`, then for `content_block_delta`, then for `text_delta`:

26 

27<CodeGroup>

28 ```python Python theme={null}

29 from claude_agent_sdk import query, ClaudeAgentOptions

30 from claude_agent_sdk.types import StreamEvent

31 import asyncio

32 

33 

34 async def stream_response():

35 options = ClaudeAgentOptions(

36 include_partial_messages=True,

37 allowed_tools=["Bash", "Read"],

38 )

39 

40 async for message in query(prompt="List the files in my project", options=options):

41 if isinstance(message, StreamEvent):

42 event = message.event

43 if event.get("type") == "content_block_delta":

44 delta = event.get("delta", {})

45 if delta.get("type") == "text_delta":

46 print(delta.get("text", ""), end="", flush=True)

47 

48 

49 asyncio.run(stream_response())

50 ```

51 

52 ```typescript TypeScript theme={null}

53 import { query } from "@anthropic-ai/claude-agent-sdk";

54 

55 for await (const message of query({

56 prompt: "List the files in my project",

57 options: {

58 includePartialMessages: true,

59 allowedTools: ["Bash", "Read"]

60 }

61 })) {

62 if (message.type === "stream_event") {

63 const event = message.event;

64 if (event.type === "content_block_delta") {

65 if (event.delta.type === "text_delta") {

66 process.stdout.write(event.delta.text);

67 }

68 }

69 }

70 }

71 ```

72</CodeGroup>

73 

74## StreamEvent reference

75 

76When partial messages are enabled, you receive raw Claude API streaming events wrapped in an object. The type has different names in each SDK:

77 

78* **Python**: `StreamEvent` (import from `claude_agent_sdk.types`)

79* **TypeScript**: `SDKPartialAssistantMessage` with `type: 'stream_event'`

80 

81Both contain raw Claude API events, not accumulated text. You need to extract and accumulate text deltas yourself. Here's the structure of each type:

82 

83<CodeGroup>

84 ```python Python theme={null}

85 @dataclass

86 class StreamEvent:

87 uuid: str # Unique identifier for this event

88 session_id: str # Session identifier

89 event: dict[str, Any] # The raw Claude API stream event

90 parent_tool_use_id: str | None # Parent tool ID if from a subagent

91 ```

92 

93 ```typescript TypeScript theme={null}

94 type SDKPartialAssistantMessage = {

95 type: "stream_event";

96 event: RawMessageStreamEvent; // From Anthropic SDK

97 parent_tool_use_id: string | null;

98 uuid: UUID;

99 session_id: string;

100 };

101 ```

102</CodeGroup>

103 

104The `event` field contains the raw streaming event from the [Claude API](https://platform.claude.com/docs/en/build-with-claude/streaming#event-types). Common event types include:

105 

106| Event Type | Description |

107| :-------------------- | :---------------------------------------------- |

108| `message_start` | Start of a new message |

109| `content_block_start` | Start of a new content block (text or tool use) |

110| `content_block_delta` | Incremental update to content |

111| `content_block_stop` | End of a content block |

112| `message_delta` | Message-level updates (stop reason, usage) |

113| `message_stop` | End of the message |

114 

115## Message flow

116 

117With partial messages enabled, you receive messages in this order:

118 

119```text theme={null}

120StreamEvent (message_start)

121StreamEvent (content_block_start) - text block

122StreamEvent (content_block_delta) - text chunks...

123StreamEvent (content_block_stop)

124StreamEvent (content_block_start) - tool_use block

125StreamEvent (content_block_delta) - tool input chunks...

126StreamEvent (content_block_stop)

127StreamEvent (message_delta)

128StreamEvent (message_stop)

129AssistantMessage - complete message with all content

130... tool executes ...

131... more streaming events for next turn ...

132ResultMessage - final result

133```

134 

135Without partial messages enabled (`include_partial_messages` in Python, `includePartialMessages` in TypeScript), you receive all message types except `StreamEvent`. Common types include `SystemMessage` (session initialization), `AssistantMessage` (complete responses), `ResultMessage` (final result), and a compact boundary message indicating when conversation history was compacted (`SDKCompactBoundaryMessage` in TypeScript; `SystemMessage` with subtype `"compact_boundary"` in Python).

136 

137## Stream text responses

138 

139To display text as it's generated, look for `content_block_delta` events where `delta.type` is `text_delta`. These contain the incremental text chunks. The example below prints each chunk as it arrives:

140 

141<CodeGroup>

142 ```python Python theme={null}

143 from claude_agent_sdk import query, ClaudeAgentOptions

144 from claude_agent_sdk.types import StreamEvent

145 import asyncio

146 

147 

148 async def stream_text():

149 options = ClaudeAgentOptions(include_partial_messages=True)

150 

151 async for message in query(prompt="Explain how databases work", options=options):

152 if isinstance(message, StreamEvent):

153 event = message.event

154 if event.get("type") == "content_block_delta":

155 delta = event.get("delta", {})

156 if delta.get("type") == "text_delta":

157 # Print each text chunk as it arrives

158 print(delta.get("text", ""), end="", flush=True)

159 

160 print() # Final newline

161 

162 

163 asyncio.run(stream_text())

164 ```

165 

166 ```typescript TypeScript theme={null}

167 import { query } from "@anthropic-ai/claude-agent-sdk";

168 

169 for await (const message of query({

170 prompt: "Explain how databases work",

171 options: { includePartialMessages: true }

172 })) {

173 if (message.type === "stream_event") {

174 const event = message.event;

175 if (event.type === "content_block_delta" && event.delta.type === "text_delta") {

176 process.stdout.write(event.delta.text);

177 }

178 }

179 }

180 

181 console.log(); // Final newline

182 ```

183</CodeGroup>

184 

185## Stream tool calls

186 

187Tool calls also stream incrementally. You can track when tools start, receive their input as it's generated, and see when they complete. The example below tracks the current tool being called and accumulates the JSON input as it streams in. It uses three event types:

188 

189* `content_block_start`: tool begins

190* `content_block_delta` with `input_json_delta`: input chunks arrive

191* `content_block_stop`: tool call complete

192 

193<CodeGroup>

194 ```python Python theme={null}

195 from claude_agent_sdk import query, ClaudeAgentOptions

196 from claude_agent_sdk.types import StreamEvent

197 import asyncio

198 

199 

200 async def stream_tool_calls():

201 options = ClaudeAgentOptions(

202 include_partial_messages=True,

203 allowed_tools=["Read", "Bash"],

204 )

205 

206 # Track the current tool and accumulate its input JSON

207 current_tool = None

208 tool_input = ""

209 

210 async for message in query(prompt="Read the README.md file", options=options):

211 if isinstance(message, StreamEvent):

212 event = message.event

213 event_type = event.get("type")

214 

215 if event_type == "content_block_start":

216 # New tool call is starting

217 content_block = event.get("content_block", {})

218 if content_block.get("type") == "tool_use":

219 current_tool = content_block.get("name")

220 tool_input = ""

221 print(f"Starting tool: {current_tool}")

222 

223 elif event_type == "content_block_delta":

224 delta = event.get("delta", {})

225 if delta.get("type") == "input_json_delta":

226 # Accumulate JSON input as it streams in

227 chunk = delta.get("partial_json", "")

228 tool_input += chunk

229 print(f" Input chunk: {chunk}")

230 

231 elif event_type == "content_block_stop":

232 # Tool call complete - show final input

233 if current_tool:

234 print(f"Tool {current_tool} called with: {tool_input}")

235 current_tool = None

236 

237 

238 asyncio.run(stream_tool_calls())

239 ```

240 

241 ```typescript TypeScript theme={null}

242 import { query } from "@anthropic-ai/claude-agent-sdk";

243 

244 // Track the current tool and accumulate its input JSON

245 let currentTool: string | null = null;

246 let toolInput = "";

247 

248 for await (const message of query({

249 prompt: "Read the README.md file",

250 options: {

251 includePartialMessages: true,

252 allowedTools: ["Read", "Bash"]

253 }

254 })) {

255 if (message.type === "stream_event") {

256 const event = message.event;

257 

258 if (event.type === "content_block_start") {

259 // New tool call is starting

260 if (event.content_block.type === "tool_use") {

261 currentTool = event.content_block.name;

262 toolInput = "";

263 console.log(`Starting tool: ${currentTool}`);

264 }

265 } else if (event.type === "content_block_delta") {

266 if (event.delta.type === "input_json_delta") {

267 // Accumulate JSON input as it streams in

268 const chunk = event.delta.partial_json;

269 toolInput += chunk;

270 console.log(` Input chunk: ${chunk}`);

271 }

272 } else if (event.type === "content_block_stop") {

273 // Tool call complete - show final input

274 if (currentTool) {

275 console.log(`Tool ${currentTool} called with: ${toolInput}`);

276 currentTool = null;

277 }

278 }

279 }

280 }

281 ```

282</CodeGroup>

283 

284## Build a streaming UI

285 

286This example combines text and tool streaming into a cohesive UI. It tracks whether the agent is currently executing a tool (using an `in_tool` flag) to show status indicators like `[Using Read...]` while tools run. Text streams normally when not in a tool, and tool completion triggers a "done" message. This pattern is useful for chat interfaces that need to show progress during multi-step agent tasks.

287 

288<CodeGroup>

289 ```python Python theme={null}

290 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

291 from claude_agent_sdk.types import StreamEvent

292 import asyncio

293 import sys

294 

295 

296 async def streaming_ui():

297 options = ClaudeAgentOptions(

298 include_partial_messages=True,

299 allowed_tools=["Read", "Bash", "Grep"],

300 )

301 

302 # Track whether we're currently in a tool call

303 in_tool = False

304 

305 async for message in query(

306 prompt="Find all TODO comments in the codebase", options=options

307 ):

308 if isinstance(message, StreamEvent):

309 event = message.event

310 event_type = event.get("type")

311 

312 if event_type == "content_block_start":

313 content_block = event.get("content_block", {})

314 if content_block.get("type") == "tool_use":

315 # Tool call is starting - show status indicator

316 tool_name = content_block.get("name")

317 print(f"\n[Using {tool_name}...]", end="", flush=True)

318 in_tool = True

319 

320 elif event_type == "content_block_delta":

321 delta = event.get("delta", {})

322 # Only stream text when not executing a tool

323 if delta.get("type") == "text_delta" and not in_tool:

324 sys.stdout.write(delta.get("text", ""))

325 sys.stdout.flush()

326 

327 elif event_type == "content_block_stop":

328 if in_tool:

329 # Tool call finished

330 print(" done", flush=True)

331 in_tool = False

332 

333 elif isinstance(message, ResultMessage):

334 # Agent finished all work

335 print(f"\n\n--- Complete ---")

336 

337 

338 asyncio.run(streaming_ui())

339 ```

340 

341 ```typescript TypeScript theme={null}

342 import { query } from "@anthropic-ai/claude-agent-sdk";

343 

344 // Track whether we're currently in a tool call

345 let inTool = false;

346 

347 for await (const message of query({

348 prompt: "Find all TODO comments in the codebase",

349 options: {

350 includePartialMessages: true,

351 allowedTools: ["Read", "Bash", "Grep"]

352 }

353 })) {

354 if (message.type === "stream_event") {

355 const event = message.event;

356 

357 if (event.type === "content_block_start") {

358 if (event.content_block.type === "tool_use") {

359 // Tool call is starting - show status indicator

360 process.stdout.write(`\n[Using ${event.content_block.name}...]`);

361 inTool = true;

362 }

363 } else if (event.type === "content_block_delta") {

364 // Only stream text when not executing a tool

365 if (event.delta.type === "text_delta" && !inTool) {

366 process.stdout.write(event.delta.text);

367 }

368 } else if (event.type === "content_block_stop") {

369 if (inTool) {

370 // Tool call finished

371 console.log(" done");

372 inTool = false;

373 }

374 }

375 } else if (message.type === "result") {

376 // Agent finished all work

377 console.log("\n\n--- Complete ---");

378 }

379 }

380 ```

381</CodeGroup>

382 

383## Known limitations

384 

385Some SDK features are incompatible with streaming:

386 

387* **Extended thinking**: when you explicitly set `max_thinking_tokens` (Python) or `maxThinkingTokens` (TypeScript), `StreamEvent` messages are not emitted. You'll only receive complete messages after each turn. Note that thinking is disabled by default in the SDK, so streaming works unless you enable it.

388* **Structured output**: the JSON result appears only in the final `ResultMessage.structured_output`, not as streaming deltas. See [structured outputs](/en/agent-sdk/structured-outputs) for details.

389 

390## Next steps

391 

392Now that you can stream text and tool calls in real-time, explore these related topics:

393 

394* [Interactive vs one-shot queries](/en/agent-sdk/streaming-vs-single-mode): choose between input modes for your use case

395* [Structured outputs](/en/agent-sdk/structured-outputs): get typed JSON responses from the agent

396* [Permissions](/en/agent-sdk/permissions): control which tools the agent can use

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# Streaming Input

6 

7> Understanding the two input modes for Claude Agent SDK and when to use each

8 

9## Overview

10 

11The Claude Agent SDK supports two distinct input modes for interacting with agents:

12 

13* **Streaming Input Mode** (Default & Recommended) - A persistent, interactive session

14* **Single Message Input** - One-shot queries that use session state and resuming

15 

16This guide explains the differences, benefits, and use cases for each mode to help you choose the right approach for your application.

17 

18## Streaming Input Mode (Recommended)

19 

20Streaming input mode is the **preferred** way to use the Claude Agent SDK. It provides full access to the agent's capabilities and enables rich, interactive experiences.

21 

22It allows the agent to operate as a long lived process that takes in user input, handles interruptions, surfaces permission requests, and handles session management.

23 

24### How It Works

25 

26```mermaid theme={null}

27sequenceDiagram

28 participant App as Your Application

29 participant Agent as Claude Agent

30 participant Tools as Tools/Hooks

31 participant FS as Environment/<br/>File System

32 

33 App->>Agent: Initialize with AsyncGenerator

34 activate Agent

35 

36 App->>Agent: Yield Message 1

37 Agent->>Tools: Execute tools

38 Tools->>FS: Read files

39 FS-->>Tools: File contents

40 Tools->>FS: Write/Edit files

41 FS-->>Tools: Success/Error

42 Agent-->>App: Stream partial response

43 Agent-->>App: Stream more content...

44 Agent->>App: Complete Message 1

45 

46 App->>Agent: Yield Message 2 + Image

47 Agent->>Tools: Process image & execute

48 Tools->>FS: Access filesystem

49 FS-->>Tools: Operation results

50 Agent-->>App: Stream response 2

51 

52 App->>Agent: Queue Message 3

53 App->>Agent: Interrupt/Cancel

54 Agent->>App: Handle interruption

55 

56 Note over App,Agent: Session stays alive

57 Note over Tools,FS: Persistent file system<br/>state maintained

58 

59 deactivate Agent

60```

61 

62### Benefits

63 

64<CardGroup cols={2}>

65 <Card title="Image Uploads" icon="image">

66 Attach images directly to messages for visual analysis and understanding

67 </Card>

68 

69 <Card title="Queued Messages" icon="stack">

70 Send multiple messages that process sequentially, with ability to interrupt

71 </Card>

72 

73 <Card title="Tool Integration" icon="wrench">

74 Full access to all tools and custom MCP servers during the session

75 </Card>

76 

77 <Card title="Hooks Support" icon="link">

78 Use lifecycle hooks to customize behavior at various points

79 </Card>

80 

81 <Card title="Real-time Feedback" icon="lightning">

82 See responses as they're generated, not just final results

83 </Card>

84 

85 <Card title="Context Persistence" icon="database">

86 Maintain conversation context across multiple turns naturally

87 </Card>

88</CardGroup>

89 

90### Implementation Example

91 

92<CodeGroup>

93 ```typescript TypeScript theme={null}

94 import { query } from "@anthropic-ai/claude-agent-sdk";

95 import { readFile } from "fs/promises";

96 

97 async function* generateMessages() {

98 // First message

99 yield {

100 type: "user" as const,

101 message: {

102 role: "user" as const,

103 content: "Analyze this codebase for security issues"

104 }

105 };

106 

107 // Wait for conditions or user input

108 await new Promise((resolve) => setTimeout(resolve, 2000));

109 

110 // Follow-up with image

111 yield {

112 type: "user" as const,

113 message: {

114 role: "user" as const,

115 content: [

116 {

117 type: "text",

118 text: "Review this architecture diagram"

119 },

120 {

121 type: "image",

122 source: {

123 type: "base64",

124 media_type: "image/png",

125 data: await readFile("diagram.png", "base64")

126 }

127 }

128 ]

129 }

130 };

131 }

132 

133 // Process streaming responses

134 for await (const message of query({

135 prompt: generateMessages(),

136 options: {

137 maxTurns: 10,

138 allowedTools: ["Read", "Grep"]

139 }

140 })) {

141 if (message.type === "result") {

142 console.log(message.result);

143 }

144 }

145 ```

146 

147 ```python Python theme={null}

148 from claude_agent_sdk import (

149 ClaudeSDKClient,

150 ClaudeAgentOptions,

151 AssistantMessage,

152 TextBlock,

153 )

154 import asyncio

155 import base64

156 

157 

158 async def streaming_analysis():

159 async def message_generator():

160 # First message

161 yield {

162 "type": "user",

163 "message": {

164 "role": "user",

165 "content": "Analyze this codebase for security issues",

166 },

167 }

168 

169 # Wait for conditions

170 await asyncio.sleep(2)

171 

172 # Follow-up with image

173 with open("diagram.png", "rb") as f:

174 image_data = base64.b64encode(f.read()).decode()

175 

176 yield {

177 "type": "user",

178 "message": {

179 "role": "user",

180 "content": [

181 {"type": "text", "text": "Review this architecture diagram"},

182 {

183 "type": "image",

184 "source": {

185 "type": "base64",

186 "media_type": "image/png",

187 "data": image_data,

188 },

189 },

190 ],

191 },

192 }

193 

194 # Use ClaudeSDKClient for streaming input

195 options = ClaudeAgentOptions(max_turns=10, allowed_tools=["Read", "Grep"])

196 

197 async with ClaudeSDKClient(options) as client:

198 # Send streaming input

199 await client.query(message_generator())

200 

201 # Process responses

202 async for message in client.receive_response():

203 if isinstance(message, AssistantMessage):

204 for block in message.content:

205 if isinstance(block, TextBlock):

206 print(block.text)

207 

208 

209 asyncio.run(streaming_analysis())

210 ```

211</CodeGroup>

212 

213## Single Message Input

214 

215Single message input is simpler but more limited.

216 

217### When to Use Single Message Input

218 

219Use single message input when:

220 

221* You need a one-shot response

222* You do not need image attachments, hooks, etc.

223* You need to operate in a stateless environment, such as a lambda function

224 

225### Limitations

226 

227<Warning>

228 Single message input mode does **not** support:

229 

230 * Direct image attachments in messages

231 * Dynamic message queueing

232 * Real-time interruption

233 * Hook integration

234 * Natural multi-turn conversations

235</Warning>

236 

237### Implementation Example

238 

239<CodeGroup>

240 ```typescript TypeScript theme={null}

241 import { query } from "@anthropic-ai/claude-agent-sdk";

242 

243 // Simple one-shot query

244 for await (const message of query({

245 prompt: "Explain the authentication flow",

246 options: {

247 maxTurns: 1,

248 allowedTools: ["Read", "Grep"]

249 }

250 })) {

251 if (message.type === "result") {

252 console.log(message.result);

253 }

254 }

255 

256 // Continue conversation with session management

257 for await (const message of query({

258 prompt: "Now explain the authorization process",

259 options: {

260 continue: true,

261 maxTurns: 1

262 }

263 })) {

264 if (message.type === "result") {

265 console.log(message.result);

266 }

267 }

268 ```

269 

270 ```python Python theme={null}

271 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

272 import asyncio

273 

274 

275 async def single_message_example():

276 # Simple one-shot query using query() function

277 async for message in query(

278 prompt="Explain the authentication flow",

279 options=ClaudeAgentOptions(max_turns=1, allowed_tools=["Read", "Grep"]),

280 ):

281 if isinstance(message, ResultMessage):

282 print(message.result)

283 

284 # Continue conversation with session management

285 async for message in query(

286 prompt="Now explain the authorization process",

287 options=ClaudeAgentOptions(continue_conversation=True, max_turns=1),

288 ):

289 if isinstance(message, ResultMessage):

290 print(message.result)

291 

292 

293 asyncio.run(single_message_example())

294 ```

295</CodeGroup>

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# Get structured output from agents

6 

7> Return validated JSON from agent workflows using JSON Schema, Zod, or Pydantic. Get type-safe, structured data after multi-turn tool use.

8 

9Structured outputs let you define the exact shape of data you want back from an agent. The agent can use any tools it needs to complete the task, and you still get validated JSON matching your schema at the end. Define a [JSON Schema](https://json-schema.org/understanding-json-schema/about) for the structure you need, and the SDK validates the output against it, re-prompting on mismatch. If validation does not succeed within the retry limit, the result is an error instead of structured data; see [Error handling](#error-handling).

10 

11For full type safety, use [Zod](#type-safe-schemas-with-zod-and-pydantic) (TypeScript) or [Pydantic](#type-safe-schemas-with-zod-and-pydantic) (Python) to define your schema and get strongly-typed objects back.

12 

13## Why structured outputs?

14 

15Agents return free-form text by default, which works for chat but not when you need to use the output programmatically. Structured outputs give you typed data you can pass directly to your application logic, database, or UI components.

16 

17Consider a recipe app where an agent searches the web and brings back recipes. Without structured outputs, you get free-form text that you'd need to parse yourself. With structured outputs, you define the shape you want and get typed data you can use directly in your app.

18 

19<AccordionGroup>

20 <Accordion title="Without structured outputs">

21 ```text theme={null}

22 Here's a classic chocolate chip cookie recipe!

23 

24 **Chocolate Chip Cookies**

25 Prep time: 15 minutes | Cook time: 10 minutes

26 

27 Ingredients:

28 - 2 1/4 cups all-purpose flour

29 - 1 cup butter, softened

30 ...

31 ```

32 

33 To use this in your app, you'd need to parse out the title, convert "15 minutes" to a number, separate ingredients from instructions, and handle inconsistent formatting across responses.

34 </Accordion>

35 

36 <Accordion title="With structured outputs">

37 ```json theme={null}

38 {

39 "name": "Chocolate Chip Cookies",

40 "prep_time_minutes": 15,

41 "cook_time_minutes": 10,

42 "ingredients": [

43 { "item": "all-purpose flour", "amount": 2.25, "unit": "cups" },

44 { "item": "butter, softened", "amount": 1, "unit": "cup" }

45 // ...

46 ],

47 "steps": ["Preheat oven to 375°F", "Cream butter and sugar" /* ... */]

48 }

49 ```

50 

51 Typed data you can use directly in your UI.

52 </Accordion>

53</AccordionGroup>

54 

55## Quick start

56 

57To use structured outputs, define a [JSON Schema](https://json-schema.org/understanding-json-schema/about) describing the shape of data you want, then pass it to `query()` via the `outputFormat` option (TypeScript) or `output_format` option (Python). When the agent finishes, the result message includes a `structured_output` field with validated data matching your schema.

58 

59The example below asks the agent to research Anthropic and return the company name, year founded, and headquarters as structured output.

60 

61<CodeGroup>

62 ```typescript TypeScript theme={null}

63 import { query } from "@anthropic-ai/claude-agent-sdk";

64 

65 // Define the shape of data you want back

66 const schema = {

67 type: "object",

68 properties: {

69 company_name: { type: "string" },

70 founded_year: { type: "number" },

71 headquarters: { type: "string" }

72 },

73 required: ["company_name"]

74 };

75 

76 for await (const message of query({

77 prompt: "Research Anthropic and provide key company information",

78 options: {

79 outputFormat: {

80 type: "json_schema",

81 schema: schema

82 }

83 }

84 })) {

85 // The result message contains structured_output with validated data

86 if (message.type === "result" && message.subtype === "success" && message.structured_output) {

87 console.log(message.structured_output);

88 // { company_name: "Anthropic", founded_year: 2021, headquarters: "San Francisco, CA" }

89 }

90 }

91 ```

92 

93 ```python Python theme={null}

94 import asyncio

95 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

96 

97 # Define the shape of data you want back

98 schema = {

99 "type": "object",

100 "properties": {

101 "company_name": {"type": "string"},

102 "founded_year": {"type": "number"},

103 "headquarters": {"type": "string"},

104 },

105 "required": ["company_name"],

106 }

107 

108 

109 async def main():

110 async for message in query(

111 prompt="Research Anthropic and provide key company information",

112 options=ClaudeAgentOptions(

113 output_format={"type": "json_schema", "schema": schema}

114 ),

115 ):

116 # The result message contains structured_output with validated data

117 if isinstance(message, ResultMessage) and message.structured_output:

118 print(message.structured_output)

119 # {'company_name': 'Anthropic', 'founded_year': 2021, 'headquarters': 'San Francisco, CA'}

120 

121 

122 asyncio.run(main())

123 ```

124</CodeGroup>

125 

126## Type-safe schemas with Zod and Pydantic

127 

128Instead of writing JSON Schema by hand, you can use [Zod](https://zod.dev/) (TypeScript) or [Pydantic](https://docs.pydantic.dev/latest/) (Python) to define your schema. These libraries generate the JSON Schema for you and let you parse the response into a fully-typed object you can use throughout your codebase with autocomplete and type checking.

129 

130The example below defines a schema for a feature implementation plan with a summary, list of steps (each with complexity level), and potential risks. The agent plans the feature and returns a typed `FeaturePlan` object. You can then access properties like `plan.summary` and iterate over `plan.steps` with full type safety.

131 

132<CodeGroup>

133 ```typescript TypeScript theme={null}

134 import { z } from "zod";

135 import { query } from "@anthropic-ai/claude-agent-sdk";

136 

137 // Define schema with Zod

138 const FeaturePlan = z.object({

139 feature_name: z.string(),

140 summary: z.string(),

141 steps: z.array(

142 z.object({

143 step_number: z.number(),

144 description: z.string(),

145 estimated_complexity: z.enum(["low", "medium", "high"])

146 })

147 ),

148 risks: z.array(z.string())

149 });

150 

151 type FeaturePlan = z.infer<typeof FeaturePlan>;

152 

153 // Convert to JSON Schema

154 const schema = z.toJSONSchema(FeaturePlan);

155 

156 // Use in query

157 for await (const message of query({

158 prompt:

159 "Plan how to add dark mode support to a React app. Break it into implementation steps.",

160 options: {

161 outputFormat: {

162 type: "json_schema",

163 schema: schema

164 }

165 }

166 })) {

167 if (message.type === "result" && message.subtype === "success" && message.structured_output) {

168 // Validate and get fully typed result

169 const parsed = FeaturePlan.safeParse(message.structured_output);

170 if (parsed.success) {

171 const plan: FeaturePlan = parsed.data;

172 console.log(`Feature: ${plan.feature_name}`);

173 console.log(`Summary: ${plan.summary}`);

174 plan.steps.forEach((step) => {

175 console.log(`${step.step_number}. [${step.estimated_complexity}] ${step.description}`);

176 });

177 }

178 }

179 }

180 ```

181 

182 ```python Python theme={null}

183 import asyncio

184 from pydantic import BaseModel

185 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

186 

187 

188 class Step(BaseModel):

189 step_number: int

190 description: str

191 estimated_complexity: str # 'low', 'medium', 'high'

192 

193 

194 class FeaturePlan(BaseModel):

195 feature_name: str

196 summary: str

197 steps: list[Step]

198 risks: list[str]

199 

200 

201 async def main():

202 async for message in query(

203 prompt="Plan how to add dark mode support to a React app. Break it into implementation steps.",

204 options=ClaudeAgentOptions(

205 output_format={

206 "type": "json_schema",

207 "schema": FeaturePlan.model_json_schema(),

208 }

209 ),

210 ):

211 if isinstance(message, ResultMessage) and message.structured_output:

212 # Validate and get fully typed result

213 plan = FeaturePlan.model_validate(message.structured_output)

214 print(f"Feature: {plan.feature_name}")

215 print(f"Summary: {plan.summary}")

216 for step in plan.steps:

217 print(

218 f"{step.step_number}. [{step.estimated_complexity}] {step.description}"

219 )

220 

221 

222 asyncio.run(main())

223 ```

224</CodeGroup>

225 

226**Benefits:**

227 

228* Full type inference (TypeScript) and type hints (Python)

229* Runtime validation with `safeParse()` or `model_validate()`

230* Better error messages

231* Composable, reusable schemas

232 

233## Output format configuration

234 

235The `outputFormat` (TypeScript) or `output_format` (Python) option accepts an object with:

236 

237* `type`: Set to `"json_schema"` for structured outputs

238* `schema`: A [JSON Schema](https://json-schema.org/understanding-json-schema/about) object defining your output structure. You can generate this from a Zod schema with `z.toJSONSchema()` or a Pydantic model with `.model_json_schema()`

239 

240The SDK supports standard JSON Schema features including all basic types (object, array, string, number, boolean, null), `enum`, `const`, `required`, nested objects, and `$ref` definitions. For the full list of supported features and limitations, see [JSON Schema limitations](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#json-schema-limitations).

241 

242## Example: TODO tracking agent

243 

244This example demonstrates how structured outputs work with multi-step tool use. The agent needs to find TODO comments in the codebase, then look up git blame information for each one. It autonomously decides which tools to use (Grep to search, Bash to run git commands) and combines the results into a single structured response.

245 

246The schema includes optional fields (`author` and `date`) since git blame information might not be available for all files. The agent fills in what it can find and omits the rest.

247 

248<CodeGroup>

249 ```typescript TypeScript theme={null}

250 import { query } from "@anthropic-ai/claude-agent-sdk";

251 

252 // Define structure for TODO extraction

253 const todoSchema = {

254 type: "object",

255 properties: {

256 todos: {

257 type: "array",

258 items: {

259 type: "object",

260 properties: {

261 text: { type: "string" },

262 file: { type: "string" },

263 line: { type: "number" },

264 author: { type: "string" },

265 date: { type: "string" }

266 },

267 required: ["text", "file", "line"]

268 }

269 },

270 total_count: { type: "number" }

271 },

272 required: ["todos", "total_count"]

273 };

274 

275 // Agent uses Grep to find TODOs, Bash to get git blame info

276 for await (const message of query({

277 prompt: "Find all TODO comments in this codebase and identify who added them",

278 options: {

279 outputFormat: {

280 type: "json_schema",

281 schema: todoSchema

282 }

283 }

284 })) {

285 if (message.type === "result" && message.subtype === "success" && message.structured_output) {

286 const data = message.structured_output as { total_count: number; todos: Array<{ file: string; line: number; text: string; author?: string; date?: string }> };

287 console.log(`Found ${data.total_count} TODOs`);

288 data.todos.forEach((todo) => {

289 console.log(`${todo.file}:${todo.line} - ${todo.text}`);

290 if (todo.author) {

291 console.log(` Added by ${todo.author} on ${todo.date}`);

292 }

293 });

294 }

295 }

296 ```

297 

298 ```python Python theme={null}

299 import asyncio

300 from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

301 

302 # Define structure for TODO extraction

303 todo_schema = {

304 "type": "object",

305 "properties": {

306 "todos": {

307 "type": "array",

308 "items": {

309 "type": "object",

310 "properties": {

311 "text": {"type": "string"},

312 "file": {"type": "string"},

313 "line": {"type": "number"},

314 "author": {"type": "string"},

315 "date": {"type": "string"},

316 },

317 "required": ["text", "file", "line"],

318 },

319 },

320 "total_count": {"type": "number"},

321 },

322 "required": ["todos", "total_count"],

323 }

324 

325 

326 async def main():

327 # Agent uses Grep to find TODOs, Bash to get git blame info

328 async for message in query(

329 prompt="Find all TODO comments in this codebase and identify who added them",

330 options=ClaudeAgentOptions(

331 output_format={"type": "json_schema", "schema": todo_schema}

332 ),

333 ):

334 if isinstance(message, ResultMessage) and message.structured_output:

335 data = message.structured_output

336 print(f"Found {data['total_count']} TODOs")

337 for todo in data["todos"]:

338 print(f"{todo['file']}:{todo['line']} - {todo['text']}")

339 if "author" in todo:

340 print(f" Added by {todo['author']} on {todo['date']}")

341 

342 

343 asyncio.run(main())

344 ```

345</CodeGroup>

346 

347## Error handling

348 

349Structured output generation can fail when the agent cannot produce valid JSON matching your schema. This typically happens when the schema is too complex for the task, the task itself is ambiguous, or the agent hits its retry limit trying to fix validation errors.

350 

351When an error occurs, the result message has a `subtype` indicating what went wrong:

352 

353| Subtype | Meaning |

354| ------------------------------------- | ----------------------------------------------------------- |

355| `success` | Output was generated and validated successfully |

356| `error_max_structured_output_retries` | Agent couldn't produce valid output after multiple attempts |

357 

358The example below checks the `subtype` field to determine whether the output was generated successfully or if you need to handle a failure:

359 

360<CodeGroup>

361 ```typescript TypeScript theme={null}

362 for await (const msg of query({

363 prompt: "Extract contact info from the document",

364 options: {

365 outputFormat: {

366 type: "json_schema",

367 schema: contactSchema

368 }

369 }

370 })) {

371 if (msg.type === "result") {

372 if (msg.subtype === "success" && msg.structured_output) {

373 // Use the validated output

374 console.log(msg.structured_output);

375 } else if (msg.subtype === "error_max_structured_output_retries") {

376 // Handle the failure - retry with simpler prompt, fall back to unstructured, etc.

377 console.error("Could not produce valid output");

378 }

379 }

380 }

381 ```

382 

383 ```python Python theme={null}

384 async for message in query(

385 prompt="Extract contact info from the document",

386 options=ClaudeAgentOptions(

387 output_format={"type": "json_schema", "schema": contact_schema}

388 ),

389 ):

390 if isinstance(message, ResultMessage):

391 if message.subtype == "success" and message.structured_output:

392 # Use the validated output

393 print(message.structured_output)

394 elif message.subtype == "error_max_structured_output_retries":

395 # Handle the failure

396 print("Could not produce valid output")

397 ```

398</CodeGroup>

399 

400**Tips for avoiding errors:**

401 

402* **Keep schemas focused.** Deeply nested schemas with many required fields are harder to satisfy. Start simple and add complexity as needed.

403* **Match schema to task.** If the task might not have all the information your schema requires, make those fields optional.

404* **Use clear prompts.** Ambiguous prompts make it harder for the agent to know what output to produce.

405 

406## Related resources

407 

408* [JSON Schema documentation](https://json-schema.org/): learn JSON Schema syntax for defining complex schemas with nested objects, arrays, enums, and validation constraints

409* [API Structured Outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs): use structured outputs with the Claude API directly for single-turn requests without tool use

410* [Custom tools](/en/agent-sdk/custom-tools): give your agent custom tools to call during execution before returning structured output

agent-sdk/subagents.md +601 −0 added

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# Subagents in the SDK

6 

7> Define and invoke subagents to isolate context, run tasks in parallel, and apply specialized instructions in your Claude Agent SDK applications.

8 

9Subagents are separate agent instances that your main agent can spawn to handle focused subtasks.

10Use subagents to isolate context for focused subtasks, run multiple analyses in parallel, and apply specialized instructions without bloating the main agent's prompt.

11 

12This guide explains how to define and use subagents in the SDK using the `agents` parameter.

13 

14## Overview

15 

16You can create subagents in three ways:

17 

18* **Programmatically**: use the `agents` parameter in your `query()` options ([TypeScript](/en/agent-sdk/typescript#agent-definition), [Python](/en/agent-sdk/python#agent-definition))

19* **Filesystem-based**: define agents as markdown files in `.claude/agents/` directories (see [defining subagents as files](/en/sub-agents))

20* **Built-in general-purpose**: Claude can invoke the built-in `general-purpose` subagent at any time via the Agent tool without you defining anything

21 

22This guide focuses on the programmatic approach, which is recommended for SDK applications.

23 

24When you define subagents, Claude determines whether to invoke them based on each subagent's `description` field. Write clear descriptions that explain when the subagent should be used, and Claude will automatically delegate appropriate tasks. You can also explicitly request a subagent by name in your prompt (for example, "Use the code-reviewer agent to...").

25 

26## Benefits of using subagents

27 

28### Context isolation

29 

30Each 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.

31 

32**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.

33 

34### Parallelization

35 

36Multiple subagents can run concurrently, dramatically speeding up complex workflows.

37 

38**Example:** during a code review, you can run `style-checker`, `security-scanner`, and `test-coverage` subagents simultaneously, reducing review time from minutes to seconds.

39 

40### Specialized instructions and knowledge

41 

42Each subagent can have tailored system prompts with specific expertise, best practices, and constraints.

43 

44**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.

45 

46### Tool restrictions

47 

48Subagents can be limited to specific tools, reducing the risk of unintended actions.

49 

50**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.

51 

52## Creating subagents

53 

54### Programmatic definition (recommended)

55 

56Define subagents directly in your code using the `agents` parameter. This example creates two subagents: a code reviewer with read-only access and a test runner that can execute commands. The `Agent` tool must be included in `allowedTools` since Claude invokes subagents through the Agent tool.

57 

58<CodeGroup>

59 ```python Python theme={null}

60 import asyncio

61 from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

62 

63 

64 async def main():

65 async for message in query(

66 prompt="Review the authentication module for security issues",

67 options=ClaudeAgentOptions(

68 # Agent tool is required for subagent invocation

69 allowed_tools=["Read", "Grep", "Glob", "Agent"],

70 agents={

71 "code-reviewer": AgentDefinition(

72 # description tells Claude when to use this subagent

73 description="Expert code review specialist. Use for quality, security, and maintainability reviews.",

74 # prompt defines the subagent's behavior and expertise

75 prompt="""You are a code review specialist with expertise in security, performance, and best practices.

76 

77 When reviewing code:

78 - Identify security vulnerabilities

79 - Check for performance issues

80 - Verify adherence to coding standards

81 - Suggest specific improvements

82 

83 Be thorough but concise in your feedback.""",

84 # tools restricts what the subagent can do (read-only here)

85 tools=["Read", "Grep", "Glob"],

86 # model overrides the default model for this subagent

87 model="sonnet",

88 ),

89 "test-runner": AgentDefinition(

90 description="Runs and analyzes test suites. Use for test execution and coverage analysis.",

91 prompt="""You are a test execution specialist. Run tests and provide clear analysis of results.

92 

93 Focus on:

94 - Running test commands

95 - Analyzing test output

96 - Identifying failing tests

97 - Suggesting fixes for failures""",

98 # Bash access lets this subagent run test commands

99 tools=["Bash", "Read", "Grep"],

100 ),

101 },

102 ),

103 ):

104 if hasattr(message, "result"):

105 print(message.result)

106 

107 

108 asyncio.run(main())

109 ```

110 

111 ```typescript TypeScript theme={null}

112 import { query } from "@anthropic-ai/claude-agent-sdk";

113 

114 for await (const message of query({

115 prompt: "Review the authentication module for security issues",

116 options: {

117 // Agent tool is required for subagent invocation

118 allowedTools: ["Read", "Grep", "Glob", "Agent"],

119 agents: {

120 "code-reviewer": {

121 // description tells Claude when to use this subagent

122 description:

123 "Expert code review specialist. Use for quality, security, and maintainability reviews.",

124 // prompt defines the subagent's behavior and expertise

125 prompt: `You are a code review specialist with expertise in security, performance, and best practices.

126 

127 When reviewing code:

128 - Identify security vulnerabilities

129 - Check for performance issues

130 - Verify adherence to coding standards

131 - Suggest specific improvements

132 

133 Be thorough but concise in your feedback.`,

134 // tools restricts what the subagent can do (read-only here)

135 tools: ["Read", "Grep", "Glob"],

136 // model overrides the default model for this subagent

137 model: "sonnet"

138 },

139 "test-runner": {

140 description:

141 "Runs and analyzes test suites. Use for test execution and coverage analysis.",

142 prompt: `You are a test execution specialist. Run tests and provide clear analysis of results.

143 

144 Focus on:

145 - Running test commands

146 - Analyzing test output

147 - Identifying failing tests

148 - Suggesting fixes for failures`,

149 // Bash access lets this subagent run test commands

150 tools: ["Bash", "Read", "Grep"]

151 }

152 }

153 }

154 })) {

155 if ("result" in message) console.log(message.result);

156 }

157 ```

158</CodeGroup>

159 

160### AgentDefinition configuration

161 

162| Field | Type | Required | Description |

163| :---------------- | :---------------------------------------------------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- |

164| `description` | `string` | Yes | Natural language description of when to use this agent |

165| `prompt` | `string` | Yes | The agent's system prompt defining its role and behavior |

166| `tools` | `string[]` | No | Array of allowed tool names. If omitted, inherits all tools |

167| `disallowedTools` | `string[]` | No | Array of tool names to remove from the agent's tool set |

168| `model` | `string` | No | Model override for this agent. Accepts an alias such as `'sonnet'`, `'opus'`, `'haiku'`, `'inherit'`, or a full model ID. Defaults to main model if omitted |

169| `skills` | `string[]` | No | List of skill names available to this agent |

170| `memory` | `'user' \| 'project' \| 'local'` | No | Memory source for this agent |

171| `mcpServers` | `(string \| object)[]` | No | MCP servers available to this agent, by name or inline config |

172| `maxTurns` | `number` | No | Maximum number of agentic turns before the agent stops |

173| `background` | `boolean` | No | Run this agent as a non-blocking background task when invoked |

174| `effort` | `'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max' \| number` | No | Reasoning effort level for this agent |

175| `permissionMode` | `PermissionMode` | No | Permission mode for tool execution within this agent |

176 

177In the Python SDK, these field names use camelCase to match the wire format. See the [`AgentDefinition` reference](/en/agent-sdk/python#agent-definition) for details.

178 

179<Note>

180 Subagents cannot spawn their own subagents. Don't include `Agent` in a subagent's `tools` array.

181</Note>

182 

183### Filesystem-based definition (alternative)

184 

185You can also define subagents as markdown files in `.claude/agents/` directories. See the [Claude Code subagents documentation](/en/sub-agents) for details on this approach. Programmatically defined agents take precedence over filesystem-based agents with the same name.

186 

187<Note>

188 Even without defining custom subagents, Claude can spawn the built-in `general-purpose` subagent when `Agent` is in your `allowedTools`. This is useful for delegating research or exploration tasks without creating specialized agents.

189</Note>

190 

191## What subagents inherit

192 

193A subagent's context window starts fresh (no parent conversation) but isn't empty. The only channel from parent to subagent is the Agent tool's prompt string, so include any file paths, error messages, or decisions the subagent needs directly in that prompt.

194 

195| The subagent receives | The subagent does not receive |

196| :--------------------------------------------------------------------------- | :------------------------------------------------- |

197| Its own system prompt (`AgentDefinition.prompt`) and the Agent tool's prompt | The parent's conversation history or tool results |

198| Project CLAUDE.md (loaded via `settingSources`) | Skills (unless listed in `AgentDefinition.skills`) |

199| Tool definitions (inherited from parent, or the subset in `tools`) | The parent's system prompt |

200 

201<Note>

202 The parent receives the subagent's final message verbatim as the Agent tool result, but may summarize it in its own response. To preserve subagent output verbatim in the user-facing response, include an instruction to do so in the prompt or `systemPrompt` option you pass to the **main** `query()` call.

203</Note>

204 

205## Invoking subagents

206 

207### Automatic invocation

208 

209Claude automatically decides when to invoke subagents based on the task and each subagent's `description`. For example, if you define a `performance-optimizer` subagent with the description "Performance optimization specialist for query tuning", Claude will invoke it when your prompt mentions optimizing queries.

210 

211Write clear, specific descriptions so Claude can match tasks to the right subagent.

212 

213### Explicit invocation

214 

215To guarantee Claude uses a specific subagent, mention it by name in your prompt:

216 

217```text theme={null}

218"Use the code-reviewer agent to check the authentication module"

219```

220 

221This bypasses automatic matching and directly invokes the named subagent.

222 

223### Dynamic agent configuration

224 

225You can create agent definitions dynamically based on runtime conditions. This example creates a security reviewer with different strictness levels, using a more powerful model for strict reviews.

226 

227<CodeGroup>

228 ```python Python theme={null}

229 import asyncio

230 from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

231 

232 

233 # Factory function that returns an AgentDefinition

234 # This pattern lets you customize agents based on runtime conditions

235 def create_security_agent(security_level: str) -> AgentDefinition:

236 is_strict = security_level == "strict"

237 return AgentDefinition(

238 description="Security code reviewer",

239 # Customize the prompt based on strictness level

240 prompt=f"You are a {'strict' if is_strict else 'balanced'} security reviewer...",

241 tools=["Read", "Grep", "Glob"],

242 # Key insight: use a more capable model for high-stakes reviews

243 model="opus" if is_strict else "sonnet",

244 )

245 

246 

247 async def main():

248 # The agent is created at query time, so each request can use different settings

249 async for message in query(

250 prompt="Review this PR for security issues",

251 options=ClaudeAgentOptions(

252 allowed_tools=["Read", "Grep", "Glob", "Agent"],

253 agents={

254 # Call the factory with your desired configuration

255 "security-reviewer": create_security_agent("strict")

256 },

257 ),

258 ):

259 if hasattr(message, "result"):

260 print(message.result)

261 

262 

263 asyncio.run(main())

264 ```

265 

266 ```typescript TypeScript theme={null}

267 import { query, type AgentDefinition } from "@anthropic-ai/claude-agent-sdk";

268 

269 // Factory function that returns an AgentDefinition

270 // This pattern lets you customize agents based on runtime conditions

271 function createSecurityAgent(securityLevel: "basic" | "strict"): AgentDefinition {

272 const isStrict = securityLevel === "strict";

273 return {

274 description: "Security code reviewer",

275 // Customize the prompt based on strictness level

276 prompt: `You are a ${isStrict ? "strict" : "balanced"} security reviewer...`,

277 tools: ["Read", "Grep", "Glob"],

278 // Key insight: use a more capable model for high-stakes reviews

279 model: isStrict ? "opus" : "sonnet"

280 };

281 }

282 

283 // The agent is created at query time, so each request can use different settings

284 for await (const message of query({

285 prompt: "Review this PR for security issues",

286 options: {

287 allowedTools: ["Read", "Grep", "Glob", "Agent"],

288 agents: {

289 // Call the factory with your desired configuration

290 "security-reviewer": createSecurityAgent("strict")

291 }

292 }

293 })) {

294 if ("result" in message) console.log(message.result);

295 }

296 ```

297</CodeGroup>

298 

299## Detecting subagent invocation

300 

301Subagents are invoked via the Agent tool. To detect when a subagent is invoked, check for `tool_use` blocks where `name` is `"Agent"`. Messages from within a subagent's context include a `parent_tool_use_id` field.

302 

303<Note>

304 The tool name was renamed from `"Task"` to `"Agent"` in Claude Code v2.1.63. Current SDK releases emit `"Agent"` in `tool_use` blocks but still use `"Task"` in the `system:init` tools list and in `result.permission_denials[].tool_name`. Checking both values in `block.name` ensures compatibility across SDK versions.

305</Note>

306 

307This example iterates through streamed messages, logging when a subagent is invoked and when subsequent messages originate from within that subagent's execution context.

308 

309<Note>

310 The message structure differs between SDKs. In Python, content blocks are accessed directly via `message.content`. In TypeScript, `SDKAssistantMessage` wraps the Claude API message, so content is accessed via `message.message.content`.

311</Note>

312 

313<CodeGroup>

314 ```python Python theme={null}

315 import asyncio

316 from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

317 

318 

319 async def main():

320 async for message in query(

321 prompt="Use the code-reviewer agent to review this codebase",

322 options=ClaudeAgentOptions(

323 allowed_tools=["Read", "Glob", "Grep", "Agent"],

324 agents={

325 "code-reviewer": AgentDefinition(

326 description="Expert code reviewer.",

327 prompt="Analyze code quality and suggest improvements.",

328 tools=["Read", "Glob", "Grep"],

329 )

330 },

331 ),

332 ):

333 # Check for subagent invocation. Match both names: older SDK

334 # versions emitted "Task", current versions emit "Agent".

335 if hasattr(message, "content") and message.content:

336 for block in message.content:

337 if getattr(block, "type", None) == "tool_use" and block.name in (

338 "Task",

339 "Agent",

340 ):

341 print(f"Subagent invoked: {block.input.get('subagent_type')}")

342 

343 # Check if this message is from within a subagent's context

344 if hasattr(message, "parent_tool_use_id") and message.parent_tool_use_id:

345 print(" (running inside subagent)")

346 

347 if hasattr(message, "result"):

348 print(message.result)

349 

350 

351 asyncio.run(main())

352 ```

353 

354 ```typescript TypeScript theme={null}

355 import { query } from "@anthropic-ai/claude-agent-sdk";

356 

357 for await (const message of query({

358 prompt: "Use the code-reviewer agent to review this codebase",

359 options: {

360 allowedTools: ["Read", "Glob", "Grep", "Agent"],

361 agents: {

362 "code-reviewer": {

363 description: "Expert code reviewer.",

364 prompt: "Analyze code quality and suggest improvements.",

365 tools: ["Read", "Glob", "Grep"]

366 }

367 }

368 }

369 })) {

370 const msg = message as any;

371 

372 // Check for subagent invocation. Match both names: older SDK versions

373 // emitted "Task", current versions emit "Agent".

374 for (const block of msg.message?.content ?? []) {

375 if (block.type === "tool_use" && (block.name === "Task" || block.name === "Agent")) {

376 console.log(`Subagent invoked: ${block.input.subagent_type}`);

377 }

378 }

379 

380 // Check if this message is from within a subagent's context

381 if (msg.parent_tool_use_id) {

382 console.log(" (running inside subagent)");

383 }

384 

385 if ("result" in message) {

386 console.log(message.result);

387 }

388 }

389 ```

390</CodeGroup>

391 

392## Resuming subagents

393 

394Subagents can be resumed to continue where they left off. Resumed subagents retain their full conversation history, including all previous tool calls, results, and reasoning. The subagent picks up exactly where it stopped rather than starting fresh.

395 

396When a subagent completes, Claude receives its agent ID in the Agent tool result. To resume a subagent programmatically:

397 

3981. **Capture the session ID**: Extract `session_id` from messages during the first query

3992. **Extract the agent ID**: Parse `agentId` from the message content

4003. **Resume the session**: Pass `resume: sessionId` in the second query's options, and include the agent ID in your prompt

401 

402<Note>

403 You must resume the same session to access the subagent's transcript. Each `query()` call starts a new session by default, so pass `resume: sessionId` to continue in the same session.

404 

405 If you're using a custom agent (not a built-in one), you also need to pass the same agent definition in the `agents` parameter for both queries.

406</Note>

407 

408The example below demonstrates this flow: the first query runs a subagent and captures the session ID and agent ID, then the second query resumes the session to ask a follow-up question that requires context from the first analysis.

409 

410<CodeGroup>

411 ```typescript TypeScript theme={null}

412 import { query, type SDKMessage } from "@anthropic-ai/claude-agent-sdk";

413 

414 // Helper to extract agentId from message content

415 // Stringify to avoid traversing different block types (TextBlock, ToolResultBlock, etc.)

416 function extractAgentId(message: SDKMessage): string | undefined {

417 if (!("message" in message)) return undefined;

418 // Stringify the content so we can search it without traversing nested blocks

419 const content = JSON.stringify(message.message.content);

420 const match = content.match(/agentId:\s*([a-f0-9-]+)/);

421 return match?.[1];

422 }

423 

424 let agentId: string | undefined;

425 let sessionId: string | undefined;

426 

427 // First invocation - use the Explore agent to find API endpoints

428 for await (const message of query({

429 prompt: "Use the Explore agent to find all API endpoints in this codebase",

430 options: { allowedTools: ["Read", "Grep", "Glob", "Agent"] }

431 })) {

432 // Capture session_id from ResultMessage (needed to resume this session)

433 if ("session_id" in message) sessionId = message.session_id;

434 // Search message content for the agentId (appears in Agent tool results)

435 const extractedId = extractAgentId(message);

436 if (extractedId) agentId = extractedId;

437 // Print the final result

438 if ("result" in message) console.log(message.result);

439 }

440 

441 // Second invocation - resume and ask follow-up

442 if (agentId && sessionId) {

443 for await (const message of query({

444 prompt: `Resume agent ${agentId} and list the top 3 most complex endpoints`,

445 options: { allowedTools: ["Read", "Grep", "Glob", "Agent"], resume: sessionId }

446 })) {

447 if ("result" in message) console.log(message.result);

448 }

449 }

450 ```

451 

452 ```python Python theme={null}

453 import asyncio

454 import json

455 import re

456 from claude_agent_sdk import query, ClaudeAgentOptions

457 

458 

459 def extract_agent_id(text: str) -> str | None:

460 """Extract agentId from Agent tool result text."""

461 match = re.search(r"agentId:\s*([a-f0-9-]+)", text)

462 return match.group(1) if match else None

463 

464 

465 async def main():

466 agent_id = None

467 session_id = None

468 

469 # First invocation - use the Explore agent to find API endpoints

470 async for message in query(

471 prompt="Use the Explore agent to find all API endpoints in this codebase",

472 options=ClaudeAgentOptions(allowed_tools=["Read", "Grep", "Glob", "Agent"]),

473 ):

474 # Capture session_id from ResultMessage (needed to resume this session)

475 if hasattr(message, "session_id"):

476 session_id = message.session_id

477 # Search message content for the agentId (appears in Agent tool results)

478 if hasattr(message, "content"):

479 # Stringify the content so we can search it without traversing nested blocks

480 content_str = json.dumps(message.content, default=str)

481 extracted = extract_agent_id(content_str)

482 if extracted:

483 agent_id = extracted

484 # Print the final result

485 if hasattr(message, "result"):

486 print(message.result)

487 

488 # Second invocation - resume and ask follow-up

489 if agent_id and session_id:

490 async for message in query(

491 prompt=f"Resume agent {agent_id} and list the top 3 most complex endpoints",

492 options=ClaudeAgentOptions(

493 allowed_tools=["Read", "Grep", "Glob", "Agent"], resume=session_id

494 ),

495 ):

496 if hasattr(message, "result"):

497 print(message.result)

498 

499 

500 asyncio.run(main())

501 ```

502</CodeGroup>

503 

504Subagent transcripts persist independently of the main conversation:

505 

506* **Main conversation compaction**: When the main conversation compacts, subagent transcripts are unaffected. They're stored in separate files.

507* **Session persistence**: Subagent transcripts persist within their session. You can resume a subagent after restarting Claude Code by resuming the same session.

508* **Automatic cleanup**: Transcripts are cleaned up based on the `cleanupPeriodDays` setting (default: 30 days).

509 

510## Tool restrictions

511 

512Subagents can have restricted tool access via the `tools` field:

513 

514* **Omit the field**: agent inherits all available tools (default)

515* **Specify tools**: agent can only use listed tools

516 

517This example creates a read-only analysis agent that can examine code but cannot modify files or run commands.

518 

519<CodeGroup>

520 ```python Python theme={null}

521 import asyncio

522 from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

523 

524 

525 async def main():

526 async for message in query(

527 prompt="Analyze the architecture of this codebase",

528 options=ClaudeAgentOptions(

529 allowed_tools=["Read", "Grep", "Glob", "Agent"],

530 agents={

531 "code-analyzer": AgentDefinition(

532 description="Static code analysis and architecture review",

533 prompt="""You are a code architecture analyst. Analyze code structure,

534 identify patterns, and suggest improvements without making changes.""",

535 # Read-only tools: no Edit, Write, or Bash access

536 tools=["Read", "Grep", "Glob"],

537 )

538 },

539 ),

540 ):

541 if hasattr(message, "result"):

542 print(message.result)

543 

544 

545 asyncio.run(main())

546 ```

547 

548 ```typescript TypeScript theme={null}

549 import { query } from "@anthropic-ai/claude-agent-sdk";

550 

551 for await (const message of query({

552 prompt: "Analyze the architecture of this codebase",

553 options: {

554 allowedTools: ["Read", "Grep", "Glob", "Agent"],

555 agents: {

556 "code-analyzer": {

557 description: "Static code analysis and architecture review",

558 prompt: `You are a code architecture analyst. Analyze code structure,

559 identify patterns, and suggest improvements without making changes.`,

560 // Read-only tools: no Edit, Write, or Bash access

561 tools: ["Read", "Grep", "Glob"]

562 }

563 }

564 }

565 })) {

566 if ("result" in message) console.log(message.result);

567 }

568 ```

569</CodeGroup>

570 

571### Common tool combinations

572 

573| Use case | Tools | Description |

574| :----------------- | :-------------------------------------- | :-------------------------------------------------- |

575| Read-only analysis | `Read`, `Grep`, `Glob` | Can examine code but not modify or execute |

576| Test execution | `Bash`, `Read`, `Grep` | Can run commands and analyze output |

577| Code modification | `Read`, `Edit`, `Write`, `Grep`, `Glob` | Full read/write access without command execution |

578| Full access | All tools | Inherits all tools from parent (omit `tools` field) |

579 

580## Troubleshooting

581 

582### Claude not delegating to subagents

583 

584If Claude completes tasks directly instead of delegating to your subagent:

585 

5861. **Include the Agent tool**: subagents are invoked via the Agent tool, so it must be in `allowedTools`

5872. **Use explicit prompting**: mention the subagent by name in your prompt (for example, "Use the code-reviewer agent to...")

5883. **Write a clear description**: explain exactly when the subagent should be used so Claude can match tasks appropriately

589 

590### Filesystem-based agents not loading

591 

592Agents defined in `.claude/agents/` are loaded at startup only. If you create a new agent file while Claude Code is running, restart the session to load it.

593 

594### Windows: long prompt failures

595 

596On Windows, subagents with very long prompts may fail due to command line length limits (8191 chars). Keep prompts concise or use filesystem-based agents for complex instructions.

597 

598## Related documentation

599 

600* [Claude Code subagents](/en/sub-agents): comprehensive subagent documentation including filesystem-based definitions

601* [SDK overview](/en/agent-sdk/overview): getting started with the Claude Agent SDK

agent-sdk/todo-tracking.md +189 −0 added

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# Todo Lists

6 

7> Track and display todos using the Claude Agent SDK for organized task management

8 

9Todo tracking provides a structured way to manage tasks and display progress to users. The Claude Agent SDK includes built-in todo functionality that helps organize complex workflows and keep users informed about task progression.

10 

11### Todo Lifecycle

12 

13Todos follow a predictable lifecycle:

14 

151. **Created** as `pending` when tasks are identified

162. **Activated** to `in_progress` when work begins

173. **Completed** when the task finishes successfully

184. **Removed** when all tasks in a group are completed

19 

20### When Todos Are Used

21 

22The SDK automatically creates todos for:

23 

24* **Complex multi-step tasks** requiring 3 or more distinct actions

25* **User-provided task lists** when multiple items are mentioned

26* **Non-trivial operations** that benefit from progress tracking

27* **Explicit requests** when users ask for todo organization

28 

29## Examples

30 

31### Monitoring Todo Changes

32 

33<CodeGroup>

34 ```typescript TypeScript theme={null}

35 import { query } from "@anthropic-ai/claude-agent-sdk";

36 

37 for await (const message of query({

38 prompt: "Optimize my React app performance and track progress with todos",

39 options: { maxTurns: 15 }

40 })) {

41 // Todo updates are reflected in the message stream

42 if (message.type === "assistant") {

43 for (const block of message.message.content) {

44 if (block.type === "tool_use" && block.name === "TodoWrite") {

45 const todos = block.input.todos;

46 

47 console.log("Todo Status Update:");

48 todos.forEach((todo, index) => {

49 const status =

50 todo.status === "completed" ? "✅" : todo.status === "in_progress" ? "🔧" : "❌";

51 console.log(`${index + 1}. ${status} ${todo.content}`);

52 });

53 }

54 }

55 }

56 }

57 ```

58 

59 ```python Python theme={null}

60 from claude_agent_sdk import query, AssistantMessage, ToolUseBlock

61 

62 async for message in query(

63 prompt="Optimize my React app performance and track progress with todos",

64 options={"max_turns": 15},

65 ):

66 # Todo updates are reflected in the message stream

67 if isinstance(message, AssistantMessage):

68 for block in message.content:

69 if isinstance(block, ToolUseBlock) and block.name == "TodoWrite":

70 todos = block.input["todos"]

71 

72 print("Todo Status Update:")

73 for i, todo in enumerate(todos):

74 status = (

75 "✅"

76 if todo["status"] == "completed"

77 else "🔧"

78 if todo["status"] == "in_progress"

79 else "❌"

80 )

81 print(f"{i + 1}. {status} {todo['content']}")

82 ```

83</CodeGroup>

84 

85### Real-time Progress Display

86 

87<CodeGroup>

88 ```typescript TypeScript theme={null}

89 import { query } from "@anthropic-ai/claude-agent-sdk";

90 

91 class TodoTracker {

92 private todos: any[] = [];

93 

94 displayProgress() {

95 if (this.todos.length === 0) return;

96 

97 const completed = this.todos.filter((t) => t.status === "completed").length;

98 const inProgress = this.todos.filter((t) => t.status === "in_progress").length;

99 const total = this.todos.length;

100 

101 console.log(`\nProgress: ${completed}/${total} completed`);

102 console.log(`Currently working on: ${inProgress} task(s)\n`);

103 

104 this.todos.forEach((todo, index) => {

105 const icon =

106 todo.status === "completed" ? "✅" : todo.status === "in_progress" ? "🔧" : "❌";

107 const text = todo.status === "in_progress" ? todo.activeForm : todo.content;

108 console.log(`${index + 1}. ${icon} ${text}`);

109 });

110 }

111 

112 async trackQuery(prompt: string) {

113 for await (const message of query({

114 prompt,

115 options: { maxTurns: 20 }

116 })) {

117 if (message.type === "assistant") {

118 for (const block of message.message.content) {

119 if (block.type === "tool_use" && block.name === "TodoWrite") {

120 this.todos = block.input.todos;

121 this.displayProgress();

122 }

123 }

124 }

125 }

126 }

127 }

128 

129 // Usage

130 const tracker = new TodoTracker();

131 await tracker.trackQuery("Build a complete authentication system with todos");

132 ```

133 

134 ```python Python theme={null}

135 from claude_agent_sdk import query, AssistantMessage, ToolUseBlock

136 from typing import List, Dict

137 

138 

139 class TodoTracker:

140 def __init__(self):

141 self.todos: List[Dict] = []

142 

143 def display_progress(self):

144 if not self.todos:

145 return

146 

147 completed = len([t for t in self.todos if t["status"] == "completed"])

148 in_progress = len([t for t in self.todos if t["status"] == "in_progress"])

149 total = len(self.todos)

150 

151 print(f"\nProgress: {completed}/{total} completed")

152 print(f"Currently working on: {in_progress} task(s)\n")

153 

154 for i, todo in enumerate(self.todos):

155 icon = (

156 "✅"

157 if todo["status"] == "completed"

158 else "🔧"

159 if todo["status"] == "in_progress"

160 else "❌"

161 )

162 text = (

163 todo["activeForm"]

164 if todo["status"] == "in_progress"

165 else todo["content"]

166 )

167 print(f"{i + 1}. {icon} {text}")

168 

169 async def track_query(self, prompt: str):

170 async for message in query(prompt=prompt, options={"max_turns": 20}):

171 if isinstance(message, AssistantMessage):

172 for block in message.content:

173 if isinstance(block, ToolUseBlock) and block.name == "TodoWrite":

174 self.todos = block.input["todos"]

175 self.display_progress()

176 

177 

178 # Usage

179 tracker = TodoTracker()

180 await tracker.track_query("Build a complete authentication system with todos")

181 ```

182</CodeGroup>

183 

184## Related Documentation

185 

186* [TypeScript SDK Reference](/en/agent-sdk/typescript)

187* [Python SDK Reference](/en/agent-sdk/python)

188* [Streaming vs Single Mode](/en/agent-sdk/streaming-vs-single-mode)

189* [Custom Tools](/en/agent-sdk/custom-tools)

agent-sdk/typescript.md +2942 −0 added

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# Agent SDK reference - TypeScript

6 

7> Complete API reference for the TypeScript Agent SDK, including all functions, types, and interfaces.

8 

9<script src="/components/typescript-sdk-type-links.js" defer />

10 

11<Note>

12 **Try the new V2 interface (preview):** A simplified interface with `send()` and `stream()` patterns is now available, making multi-turn conversations easier. [Learn more about the TypeScript V2 preview](/en/agent-sdk/typescript-v2-preview)

13</Note>

14 

15## Installation

16 

17```bash theme={null}

18npm install @anthropic-ai/claude-agent-sdk

19```

20 

21<Note>

22 The SDK bundles a native Claude Code binary for your platform as an optional dependency such as `@anthropic-ai/claude-agent-sdk-darwin-arm64`. You don't need to install Claude Code separately. If your package manager skips optional dependencies, the SDK throws `Native CLI binary for <platform> not found`; set [`pathToClaudeCodeExecutable`](#options) to a separately installed `claude` binary instead.

23</Note>

24 

25## Functions

26 

27### `query()`

28 

29The primary function for interacting with Claude Code. Creates an async generator that streams messages as they arrive.

30 

31```typescript theme={null}

32function query({

33 prompt,

34 options

35}: {

36 prompt: string | AsyncIterable<SDKUserMessage>;

37 options?: Options;

38}): Query;

39```

40 

41#### Parameters

42 

43| Parameter | Type | Description |

44| :-------- | :---------------------------------------------------------------- | :---------------------------------------------------------------- |

45| `prompt` | `string \| AsyncIterable<`[`SDKUserMessage`](#sdkuser-message)`>` | The input prompt as a string or async iterable for streaming mode |

46| `options` | [`Options`](#options) | Optional configuration object (see Options type below) |

47 

48#### Returns

49 

50Returns a [`Query`](#query-object) object that extends `AsyncGenerator<`[`SDKMessage`](#sdk-message)`, void>` with additional methods.

51 

52### `startup()`

53 

54Pre-warms the CLI subprocess by spawning it and completing the initialize handshake before a prompt is available. The returned [`WarmQuery`](#warm-query) handle accepts a prompt later and writes it to an already-ready process, so the first `query()` call resolves without paying subprocess spawn and initialization cost inline.

55 

56```typescript theme={null}

57function startup(params?: {

58 options?: Options;

59 initializeTimeoutMs?: number;

60}): Promise<WarmQuery>;

61```

62 

63#### Parameters

64 

65| Parameter | Type | Description |

66| :-------------------- | :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

67| `options` | [`Options`](#options) | Optional configuration object. Same as the `options` parameter to `query()` |

68| `initializeTimeoutMs` | `number` | Maximum time in milliseconds to wait for subprocess initialization. Defaults to `60000`. If initialization does not complete in time, the promise rejects with a timeout error |

69 

70#### Returns

71 

72Returns a `Promise<`[`WarmQuery`](#warm-query)`>` that resolves once the subprocess has spawned and completed its initialize handshake.

73 

74#### Example

75 

76Call `startup()` early, for example on application boot, then call `.query()` on the returned handle once a prompt is ready. This moves subprocess spawn and initialization out of the critical path.

77 

78```typescript theme={null}

79import { startup } from "@anthropic-ai/claude-agent-sdk";

80 

81// Pay startup cost upfront

82const warm = await startup({ options: { maxTurns: 3 } });

83 

84// Later, when a prompt is ready, this is immediate

85for await (const message of warm.query("What files are here?")) {

86 console.log(message);

87}

88```

89 

90### `tool()`

91 

92Creates a type-safe MCP tool definition for use with SDK MCP servers.

93 

94```typescript theme={null}

95function tool<Schema extends AnyZodRawShape>(

96 name: string,

97 description: string,

98 inputSchema: Schema,

99 handler: (args: InferShape<Schema>, extra: unknown) => Promise<CallToolResult>,

100 extras?: { annotations?: ToolAnnotations }

101): SdkMcpToolDefinition<Schema>;

102```

103 

104#### Parameters

105 

106| Parameter | Type | Description |

107| :------------ | :------------------------------------------------------------------ | :------------------------------------------------------------------------------ |

108| `name` | `string` | The name of the tool |

109| `description` | `string` | A description of what the tool does |

110| `inputSchema` | `Schema extends AnyZodRawShape` | Zod schema defining the tool's input parameters (supports both Zod 3 and Zod 4) |

111| `handler` | `(args, extra) => Promise<`[`CallToolResult`](#call-tool-result)`>` | Async function that executes the tool logic |

112| `extras` | `{ annotations?: `[`ToolAnnotations`](#tool-annotations)` }` | Optional MCP tool annotations providing behavioral hints to clients |

113 

114#### `ToolAnnotations`

115 

116Re-exported from `@modelcontextprotocol/sdk/types.js`. All fields are optional hints; clients should not rely on them for security decisions.

117 

118| Field | Type | Default | Description |

119| :---------------- | :-------- | :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- |

120| `title` | `string` | `undefined` | Human-readable title for the tool |

121| `readOnlyHint` | `boolean` | `false` | If `true`, the tool does not modify its environment |

122| `destructiveHint` | `boolean` | `true` | If `true`, the tool may perform destructive updates (only meaningful when `readOnlyHint` is `false`) |

123| `idempotentHint` | `boolean` | `false` | If `true`, repeated calls with the same arguments have no additional effect (only meaningful when `readOnlyHint` is `false`) |

124| `openWorldHint` | `boolean` | `true` | If `true`, the tool interacts with external entities (for example, web search). If `false`, the tool's domain is closed (for example, a memory tool) |

125 

126```typescript theme={null}

127import { tool } from "@anthropic-ai/claude-agent-sdk";

128import { z } from "zod";

129 

130const searchTool = tool(

131 "search",

132 "Search the web",

133 { query: z.string() },

134 async ({ query }) => {

135 return { content: [{ type: "text", text: `Results for: ${query}` }] };

136 },

137 { annotations: { readOnlyHint: true, openWorldHint: true } }

138);

139```

140 

141### `createSdkMcpServer()`

142 

143Creates an MCP server instance that runs in the same process as your application.

144 

145```typescript theme={null}

146function createSdkMcpServer(options: {

147 name: string;

148 version?: string;

149 tools?: Array<SdkMcpToolDefinition<any>>;

150}): McpSdkServerConfigWithInstance;

151```

152 

153#### Parameters

154 

155| Parameter | Type | Description |

156| :---------------- | :---------------------------- | :------------------------------------------------------- |

157| `options.name` | `string` | The name of the MCP server |

158| `options.version` | `string` | Optional version string |

159| `options.tools` | `Array<SdkMcpToolDefinition>` | Array of tool definitions created with [`tool()`](#tool) |

160 

161### `listSessions()`

162 

163Discovers and lists past sessions with light metadata. Filter by project directory or list sessions across all projects.

164 

165```typescript theme={null}

166function listSessions(options?: ListSessionsOptions): Promise<SDKSessionInfo[]>;

167```

168 

169#### Parameters

170 

171| Parameter | Type | Default | Description |

172| :------------------------- | :-------- | :---------- | :--------------------------------------------------------------------------------- |

173| `options.dir` | `string` | `undefined` | Directory to list sessions for. When omitted, returns sessions across all projects |

174| `options.limit` | `number` | `undefined` | Maximum number of sessions to return |

175| `options.includeWorktrees` | `boolean` | `true` | When `dir` is inside a git repository, include sessions from all worktree paths |

176 

177#### Return type: `SDKSessionInfo`

178 

179| Property | Type | Description |

180| :------------- | :-------------------- | :-------------------------------------------------------------------------- |

181| `sessionId` | `string` | Unique session identifier (UUID) |

182| `summary` | `string` | Display title: custom title, auto-generated summary, or first prompt |

183| `lastModified` | `number` | Last modified time in milliseconds since epoch |

184| `fileSize` | `number \| undefined` | Session file size in bytes. Only populated for local JSONL storage |

185| `customTitle` | `string \| undefined` | User-set session title (via `/rename`) |

186| `firstPrompt` | `string \| undefined` | First meaningful user prompt in the session |

187| `gitBranch` | `string \| undefined` | Git branch at the end of the session |

188| `cwd` | `string \| undefined` | Working directory for the session |

189| `tag` | `string \| undefined` | User-set session tag (see [`tagSession()`](#tag-session)) |

190| `createdAt` | `number \| undefined` | Creation time in milliseconds since epoch, from the first entry's timestamp |

191 

192#### Example

193 

194Print the 10 most recent sessions for a project. Results are sorted by `lastModified` descending, so the first item is the newest. Omit `dir` to search across all projects.

195 

196```typescript theme={null}

197import { listSessions } from "@anthropic-ai/claude-agent-sdk";

198 

199const sessions = await listSessions({ dir: "/path/to/project", limit: 10 });

200 

201for (const session of sessions) {

202 console.log(`${session.summary} (${session.sessionId})`);

203}

204```

205 

206### `getSessionMessages()`

207 

208Reads user and assistant messages from a past session transcript.

209 

210```typescript theme={null}

211function getSessionMessages(

212 sessionId: string,

213 options?: GetSessionMessagesOptions

214): Promise<SessionMessage[]>;

215```

216 

217#### Parameters

218 

219| Parameter | Type | Default | Description |

220| :--------------- | :------- | :---------- | :---------------------------------------------------------------------------- |

221| `sessionId` | `string` | required | Session UUID to read (see `listSessions()`) |

222| `options.dir` | `string` | `undefined` | Project directory to find the session in. When omitted, searches all projects |

223| `options.limit` | `number` | `undefined` | Maximum number of messages to return |

224| `options.offset` | `number` | `undefined` | Number of messages to skip from the start |

225 

226#### Return type: `SessionMessage`

227 

228| Property | Type | Description |

229| :------------------- | :---------------------- | :-------------------------------------- |

230| `type` | `"user" \| "assistant"` | Message role |

231| `uuid` | `string` | Unique message identifier |

232| `session_id` | `string` | Session this message belongs to |

233| `message` | `unknown` | Raw message payload from the transcript |

234| `parent_tool_use_id` | `null` | Reserved |

235 

236#### Example

237 

238```typescript theme={null}

239import { listSessions, getSessionMessages } from "@anthropic-ai/claude-agent-sdk";

240 

241const [latest] = await listSessions({ dir: "/path/to/project", limit: 1 });

242 

243if (latest) {

244 const messages = await getSessionMessages(latest.sessionId, {

245 dir: "/path/to/project",

246 limit: 20

247 });

248 

249 for (const msg of messages) {

250 console.log(`[${msg.type}] ${msg.uuid}`);

251 }

252}

253```

254 

255### `getSessionInfo()`

256 

257Reads metadata for a single session by ID without scanning the full project directory.

258 

259```typescript theme={null}

260function getSessionInfo(

261 sessionId: string,

262 options?: GetSessionInfoOptions

263): Promise<SDKSessionInfo | undefined>;

264```

265 

266#### Parameters

267 

268| Parameter | Type | Default | Description |

269| :------------ | :------- | :---------- | :--------------------------------------------------------------------- |

270| `sessionId` | `string` | required | UUID of the session to look up |

271| `options.dir` | `string` | `undefined` | Project directory path. When omitted, searches all project directories |

272 

273Returns [`SDKSessionInfo`](#return-type-sdk-session-info), or `undefined` if the session is not found.

274 

275### `renameSession()`

276 

277Renames a session by appending a custom-title entry. Repeated calls are safe; the most recent title wins.

278 

279```typescript theme={null}

280function renameSession(

281 sessionId: string,

282 title: string,

283 options?: SessionMutationOptions

284): Promise<void>;

285```

286 

287#### Parameters

288 

289| Parameter | Type | Default | Description |

290| :------------ | :------- | :---------- | :--------------------------------------------------------------------- |

291| `sessionId` | `string` | required | UUID of the session to rename |

292| `title` | `string` | required | New title. Must be non-empty after trimming whitespace |

293| `options.dir` | `string` | `undefined` | Project directory path. When omitted, searches all project directories |

294 

295### `tagSession()`

296 

297Tags a session. Pass `null` to clear the tag. Repeated calls are safe; the most recent tag wins.

298 

299```typescript theme={null}

300function tagSession(

301 sessionId: string,

302 tag: string | null,

303 options?: SessionMutationOptions

304): Promise<void>;

305```

306 

307#### Parameters

308 

309| Parameter | Type | Default | Description |

310| :------------ | :--------------- | :---------- | :--------------------------------------------------------------------- |

311| `sessionId` | `string` | required | UUID of the session to tag |

312| `tag` | `string \| null` | required | Tag string, or `null` to clear |

313| `options.dir` | `string` | `undefined` | Project directory path. When omitted, searches all project directories |

314 

315## Types

316 

317### `Options`

318 

319Configuration object for the `query()` function.

320 

321| Property | Type | Default | Description |

322| :-------------------------------- | :------------------------------------------------------------------------------------------------------- | :------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

323| `abortController` | `AbortController` | `new AbortController()` | Controller for cancelling operations |

324| `additionalDirectories` | `string[]` | `[]` | Additional directories Claude can access |

325| `agent` | `string` | `undefined` | Agent name for the main thread. The agent must be defined in the `agents` option or in settings |

326| `agents` | `Record<string, [`AgentDefinition`](#agent-definition)>` | `undefined` | Programmatically define subagents |

327| `allowDangerouslySkipPermissions` | `boolean` | `false` | Enable bypassing permissions. Required when using `permissionMode: 'bypassPermissions'` |

328| `allowedTools` | `string[]` | `[]` | Tools to auto-approve without prompting. This does not restrict Claude to only these tools; unlisted tools fall through to `permissionMode` and `canUseTool`. Use `disallowedTools` to block tools. See [Permissions](/en/agent-sdk/permissions#allow-and-deny-rules) |

329| `betas` | [`SdkBeta`](#sdk-beta)`[]` | `[]` | Enable beta features |

330| `canUseTool` | [`CanUseTool`](#can-use-tool) | `undefined` | Custom permission function for tool usage |

331| `continue` | `boolean` | `false` | Continue the most recent conversation |

332| `cwd` | `string` | `process.cwd()` | Current working directory |

333| `debug` | `boolean` | `false` | Enable debug mode for the Claude Code process |

334| `debugFile` | `string` | `undefined` | Write debug logs to a specific file path. Implicitly enables debug mode |

335| `disallowedTools` | `string[]` | `[]` | Tools to always deny. Deny rules are checked first and override `allowedTools` and `permissionMode` (including `bypassPermissions`) |

336| `effort` | `'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max'` | `'high'` | Controls how much effort Claude puts into its response. Works with adaptive thinking to guide thinking depth |

337| `enableFileCheckpointing` | `boolean` | `false` | Enable file change tracking for rewinding. See [File checkpointing](/en/agent-sdk/file-checkpointing) |

338| `env` | `Record<string, string \| undefined>` | `process.env` | Environment variables. See [Environment variables](/en/env-vars) for variables the underlying CLI reads. Set `CLAUDE_AGENT_SDK_CLIENT_APP` to identify your app in the User-Agent header |

339| `executable` | `'bun' \| 'deno' \| 'node'` | Auto-detected | JavaScript runtime to use |

340| `executableArgs` | `string[]` | `[]` | Arguments to pass to the executable |

341| `extraArgs` | `Record<string, string \| null>` | `{}` | Additional arguments |

342| `fallbackModel` | `string` | `undefined` | Model to use if primary fails |

343| `forkSession` | `boolean` | `false` | When resuming with `resume`, fork to a new session ID instead of continuing the original session |

344| `hooks` | `Partial<Record<`[`HookEvent`](#hook-event)`, `[`HookCallbackMatcher`](#hook-callback-matcher)`[]>>` | `{}` | Hook callbacks for events |

345| `includePartialMessages` | `boolean` | `false` | Include partial message events |

346| `maxBudgetUsd` | `number` | `undefined` | Stop the query when the client-side cost estimate reaches this USD value. Compared against the same estimate as `total_cost_usd`; see [Track cost and usage](/en/agent-sdk/cost-tracking) for accuracy caveats |

347| `maxThinkingTokens` | `number` | `undefined` | *Deprecated:* Use `thinking` instead. Maximum tokens for thinking process |

348| `maxTurns` | `number` | `undefined` | Maximum agentic turns (tool-use round trips) |

349| `mcpServers` | `Record<string, [`McpServerConfig`](#mcp-server-config)>` | `{}` | MCP server configurations |

350| `model` | `string` | Default from CLI | Claude model to use |

351| `outputFormat` | `{ type: 'json_schema', schema: JSONSchema }` | `undefined` | Define output format for agent results. See [Structured outputs](/en/agent-sdk/structured-outputs) for details |

352| `pathToClaudeCodeExecutable` | `string` | Auto-resolved from bundled native binary | Path to Claude Code executable. Only needed if optional dependencies were skipped during install or your platform isn't in the supported set |

353| `permissionMode` | [`PermissionMode`](#permission-mode) | `'default'` | Permission mode for the session |

354| `permissionPromptToolName` | `string` | `undefined` | MCP tool name for permission prompts |

355| `persistSession` | `boolean` | `true` | When `false`, disables session persistence to disk. Sessions cannot be resumed later |

356| `plugins` | [`SdkPluginConfig`](#sdk-plugin-config)`[]` | `[]` | Load custom plugins from local paths. See [Plugins](/en/agent-sdk/plugins) for details |

357| `promptSuggestions` | `boolean` | `false` | Enable prompt suggestions. Emits a `prompt_suggestion` message after each turn with a predicted next user prompt |

358| `resume` | `string` | `undefined` | Session ID to resume |

359| `resumeSessionAt` | `string` | `undefined` | Resume session at a specific message UUID |

360| `sandbox` | [`SandboxSettings`](#sandbox-settings) | `undefined` | Configure sandbox behavior programmatically. See [Sandbox settings](#sandbox-settings) for details |

361| `sessionId` | `string` | Auto-generated | Use a specific UUID for the session instead of auto-generating one |

362| `sessionStore` | [`SessionStore`](/en/agent-sdk/session-storage#the-session-store-interface) | `undefined` | Mirror session transcripts to an external backend so any host can resume them. See [Persist sessions to external storage](/en/agent-sdk/session-storage) |

363| `settingSources` | [`SettingSource`](#setting-source)`[]` | CLI defaults (all sources) | Control which filesystem settings to load. Pass `[]` to disable user, project, and local settings. Managed policy settings load regardless. See [Use Claude Code features](/en/agent-sdk/claude-code-features#what-settingsources-does-not-control) |

364| `spawnClaudeCodeProcess` | `(options: SpawnOptions) => SpawnedProcess` | `undefined` | Custom function to spawn the Claude Code process. Use to run Claude Code in VMs, containers, or remote environments |

365| `stderr` | `(data: string) => void` | `undefined` | Callback for stderr output |

366| `strictMcpConfig` | `boolean` | `false` | Enforce strict MCP validation |

367| `systemPrompt` | `string \| { type: 'preset'; preset: 'claude_code'; append?: string; excludeDynamicSections?: boolean }` | `undefined` (minimal prompt) | System prompt configuration. Pass a string for custom prompt, or `{ type: 'preset', preset: 'claude_code' }` to use Claude Code's system prompt. When using the preset object form, add `append` to extend it with additional instructions, and set `excludeDynamicSections: true` to move per-session context into the first user message for [better prompt-cache reuse across machines](/en/agent-sdk/modifying-system-prompts#improve-prompt-caching-across-users-and-machines) |

368| `thinking` | [`ThinkingConfig`](#thinking-config) | `{ type: 'adaptive' }` for supported models | Controls Claude's thinking/reasoning behavior. See [`ThinkingConfig`](#thinking-config) for options |

369| `toolConfig` | [`ToolConfig`](#tool-config) | `undefined` | Configuration for built-in tool behavior. See [`ToolConfig`](#tool-config) for details |

370| `tools` | `string[] \| { type: 'preset'; preset: 'claude_code' }` | `undefined` | Tool configuration. Pass an array of tool names or use the preset to get Claude Code's default tools |

371 

372### `Query` object

373 

374Interface returned by the `query()` function.

375 

376```typescript theme={null}

377interface Query extends AsyncGenerator<SDKMessage, void> {

378 interrupt(): Promise<void>;

379 rewindFiles(

380 userMessageId: string,

381 options?: { dryRun?: boolean }

382 ): Promise<RewindFilesResult>;

383 setPermissionMode(mode: PermissionMode): Promise<void>;

384 setModel(model?: string): Promise<void>;

385 setMaxThinkingTokens(maxThinkingTokens: number | null): Promise<void>;

386 initializationResult(): Promise<SDKControlInitializeResponse>;

387 supportedCommands(): Promise<SlashCommand[]>;

388 supportedModels(): Promise<ModelInfo[]>;

389 supportedAgents(): Promise<AgentInfo[]>;

390 mcpServerStatus(): Promise<McpServerStatus[]>;

391 accountInfo(): Promise<AccountInfo>;

392 reconnectMcpServer(serverName: string): Promise<void>;

393 toggleMcpServer(serverName: string, enabled: boolean): Promise<void>;

394 setMcpServers(servers: Record<string, McpServerConfig>): Promise<McpSetServersResult>;

395 streamInput(stream: AsyncIterable<SDKUserMessage>): Promise<void>;

396 stopTask(taskId: string): Promise<void>;

397 close(): void;

398}

399```

400 

401#### Methods

402 

403| Method | Description |

404| :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

405| `interrupt()` | Interrupts the query (only available in streaming input mode) |

406| `rewindFiles(userMessageId, options?)` | Restores files to their state at the specified user message. Pass `{ dryRun: true }` to preview changes. Requires `enableFileCheckpointing: true`. See [File checkpointing](/en/agent-sdk/file-checkpointing) |

407| `setPermissionMode()` | Changes the permission mode (only available in streaming input mode) |

408| `setModel()` | Changes the model (only available in streaming input mode) |

409| `setMaxThinkingTokens()` | *Deprecated:* Use the `thinking` option instead. Changes the maximum thinking tokens |

410| `initializationResult()` | Returns the full initialization result including supported commands, models, account info, and output style configuration |

411| `supportedCommands()` | Returns available slash commands |

412| `supportedModels()` | Returns available models with display info |

413| `supportedAgents()` | Returns available subagents as [`AgentInfo`](#agent-info)`[]` |

414| `mcpServerStatus()` | Returns status of connected MCP servers |

415| `accountInfo()` | Returns account information |

416| `reconnectMcpServer(serverName)` | Reconnect an MCP server by name |

417| `toggleMcpServer(serverName, enabled)` | Enable or disable an MCP server by name |

418| `setMcpServers(servers)` | Dynamically replace the set of MCP servers for this session. Returns info about which servers were added, removed, and any errors |

419| `streamInput(stream)` | Stream input messages to the query for multi-turn conversations |

420| `stopTask(taskId)` | Stop a running background task by ID |

421| `close()` | Close the query and terminate the underlying process. Forcefully ends the query and cleans up all resources |

422 

423### `WarmQuery`

424 

425Handle returned by [`startup()`](#startup). The subprocess is already spawned and initialized, so calling `query()` on this handle writes the prompt directly to a ready process with no startup latency.

426 

427```typescript theme={null}

428interface WarmQuery extends AsyncDisposable {

429 query(prompt: string | AsyncIterable<SDKUserMessage>): Query;

430 close(): void;

431}

432```

433 

434#### Methods

435 

436| Method | Description |

437| :-------------- | :------------------------------------------------------------------------------------------------------------------------ |

438| `query(prompt)` | Send a prompt to the pre-warmed subprocess and return a [`Query`](#query-object). Can only be called once per `WarmQuery` |

439| `close()` | Close the subprocess without sending a prompt. Use this to discard a warm query that is no longer needed |

440 

441`WarmQuery` implements `AsyncDisposable`, so it can be used with `await using` for automatic cleanup.

442 

443### `SDKControlInitializeResponse`

444 

445Return type of `initializationResult()`. Contains session initialization data.

446 

447```typescript theme={null}

448type SDKControlInitializeResponse = {

449 commands: SlashCommand[];

450 agents: AgentInfo[];

451 output_style: string;

452 available_output_styles: string[];

453 models: ModelInfo[];

454 account: AccountInfo;

455 fast_mode_state?: "off" | "cooldown" | "on";

456};

457```

458 

459### `AgentDefinition`

460 

461Configuration for a subagent defined programmatically.

462 

463```typescript theme={null}

464type AgentDefinition = {

465 description: string;

466 tools?: string[];

467 disallowedTools?: string[];

468 prompt: string;

469 model?: string;

470 mcpServers?: AgentMcpServerSpec[];

471 skills?: string[];

472 initialPrompt?: string;

473 maxTurns?: number;

474 background?: boolean;

475 memory?: "user" | "project" | "local";

476 effort?: "low" | "medium" | "high" | "xhigh" | "max" | number;

477 permissionMode?: PermissionMode;

478 criticalSystemReminder_EXPERIMENTAL?: string;

479};

480```

481 

482| Field | Required | Description |

483| :------------------------------------ | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

484| `description` | Yes | Natural language description of when to use this agent |

485| `tools` | No | Array of allowed tool names. If omitted, inherits all tools from parent |

486| `disallowedTools` | No | Array of tool names to explicitly disallow for this agent |

487| `prompt` | Yes | The agent's system prompt |

488| `model` | No | Model override for this agent. Accepts an alias such as `'sonnet'`, `'opus'`, `'haiku'`, `'inherit'`, or a full model ID. If omitted or `'inherit'`, uses the main model |

489| `mcpServers` | No | MCP server specifications for this agent |

490| `skills` | No | Array of skill names to preload into the agent context |

491| `initialPrompt` | No | Auto-submitted as the first user turn when this agent runs as the main thread agent |

492| `maxTurns` | No | Maximum number of agentic turns (API round-trips) before stopping |

493| `background` | No | Run this agent as a non-blocking background task when invoked |

494| `memory` | No | Memory source for this agent: `'user'`, `'project'`, or `'local'` |

495| `effort` | No | Reasoning effort level for this agent. Accepts a named level or an integer |

496| `permissionMode` | No | Permission mode for tool execution within this agent. See [`PermissionMode`](#permission-mode) |

497| `criticalSystemReminder_EXPERIMENTAL` | No | Experimental: Critical reminder added to the system prompt |

498 

499### `AgentMcpServerSpec`

500 

501Specifies MCP servers available to a subagent. Can be a server name (string referencing a server from the parent's `mcpServers` config) or an inline server configuration record mapping server names to configs.

502 

503```typescript theme={null}

504type AgentMcpServerSpec = string | Record<string, McpServerConfigForProcessTransport>;

505```

506 

507Where `McpServerConfigForProcessTransport` is `McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig`.

508 

509### `SettingSource`

510 

511Controls which filesystem-based configuration sources the SDK loads settings from.

512 

513```typescript theme={null}

514type SettingSource = "user" | "project" | "local";

515```

516 

517| Value | Description | Location |

518| :---------- | :------------------------------------------- | :---------------------------- |

519| `'user'` | Global user settings | `~/.claude/settings.json` |

520| `'project'` | Shared project settings (version controlled) | `.claude/settings.json` |

521| `'local'` | Local project settings (gitignored) | `.claude/settings.local.json` |

522 

523#### Default behavior

524 

525When `settingSources` is omitted or `undefined`, `query()` loads the same filesystem settings as the Claude Code CLI: user, project, and local. Managed policy settings are loaded in all cases. See [What settingSources does not control](/en/agent-sdk/claude-code-features#what-settingsources-does-not-control) for inputs that are read regardless of this option, and how to disable them.

526 

527#### Why use settingSources

528 

529**Disable filesystem settings:**

530 

531```typescript theme={null}

532// Do not load user, project, or local settings from disk

533const result = query({

534 prompt: "Analyze this code",

535 options: { settingSources: [] }

536});

537```

538 

539**Load all filesystem settings explicitly:**

540 

541```typescript theme={null}

542const result = query({

543 prompt: "Analyze this code",

544 options: {

545 settingSources: ["user", "project", "local"] // Load all settings

546 }

547});

548```

549 

550**Load only specific setting sources:**

551 

552```typescript theme={null}

553// Load only project settings, ignore user and local

554const result = query({

555 prompt: "Run CI checks",

556 options: {

557 settingSources: ["project"] // Only .claude/settings.json

558 }

559});

560```

561 

562**Testing and CI environments:**

563 

564```typescript theme={null}

565// Ensure consistent behavior in CI by excluding local settings

566const result = query({

567 prompt: "Run tests",

568 options: {

569 settingSources: ["project"], // Only team-shared settings

570 permissionMode: "bypassPermissions"

571 }

572});

573```

574 

575**SDK-only applications:**

576 

577```typescript theme={null}

578// Define everything programmatically.

579// Pass [] to opt out of filesystem setting sources.

580const result = query({

581 prompt: "Review this PR",

582 options: {

583 settingSources: [],

584 agents: {

585 /* ... */

586 },

587 mcpServers: {

588 /* ... */

589 },

590 allowedTools: ["Read", "Grep", "Glob"]

591 }

592});

593```

594 

595**Loading CLAUDE.md project instructions:**

596 

597```typescript theme={null}

598// Load project settings to include CLAUDE.md files

599const result = query({

600 prompt: "Add a new feature following project conventions",

601 options: {

602 systemPrompt: {

603 type: "preset",

604 preset: "claude_code" // Use Claude Code's system prompt

605 },

606 settingSources: ["project"], // Loads CLAUDE.md from project directory

607 allowedTools: ["Read", "Write", "Edit"]

608 }

609});

610```

611 

612#### Settings precedence

613 

614When multiple sources are loaded, settings are merged with this precedence (highest to lowest):

615 

6161. Local settings (`.claude/settings.local.json`)

6172. Project settings (`.claude/settings.json`)

6183. User settings (`~/.claude/settings.json`)

619 

620Programmatic options such as `agents` and `allowedTools` override user, project, and local filesystem settings. Managed policy settings take precedence over programmatic options.

621 

622### `PermissionMode`

623 

624```typescript theme={null}

625type PermissionMode =

626 | "default" // Standard permission behavior

627 | "acceptEdits" // Auto-accept file edits

628 | "bypassPermissions" // Bypass all permission checks

629 | "plan" // Planning mode - no execution

630 | "dontAsk" // Don't prompt for permissions, deny if not pre-approved

631 | "auto"; // Use a model classifier to approve or deny each tool call

632```

633 

634### `CanUseTool`

635 

636Custom permission function type for controlling tool usage.

637 

638```typescript theme={null}

639type CanUseTool = (

640 toolName: string,

641 input: Record<string, unknown>,

642 options: {

643 signal: AbortSignal;

644 suggestions?: PermissionUpdate[];

645 blockedPath?: string;

646 decisionReason?: string;

647 toolUseID: string;

648 agentID?: string;

649 }

650) => Promise<PermissionResult>;

651```

652 

653| Option | Type | Description |

654| :--------------- | :------------------------------------------- | :--------------------------------------------------------------------------- |

655| `signal` | `AbortSignal` | Signaled if the operation should be aborted |

656| `suggestions` | [`PermissionUpdate`](#permission-update)`[]` | Suggested permission updates so the user is not prompted again for this tool |

657| `blockedPath` | `string` | The file path that triggered the permission request, if applicable |

658| `decisionReason` | `string` | Explains why this permission request was triggered |

659| `toolUseID` | `string` | Unique identifier for this specific tool call within the assistant message |

660| `agentID` | `string` | If running within a sub-agent, the sub-agent's ID |

661 

662### `PermissionResult`

663 

664Result of a permission check.

665 

666```typescript theme={null}

667type PermissionResult =

668 | {

669 behavior: "allow";

670 updatedInput?: Record<string, unknown>;

671 updatedPermissions?: PermissionUpdate[];

672 toolUseID?: string;

673 }

674 | {

675 behavior: "deny";

676 message: string;

677 interrupt?: boolean;

678 toolUseID?: string;

679 };

680```

681 

682### `ToolConfig`

683 

684Configuration for built-in tool behavior.

685 

686```typescript theme={null}

687type ToolConfig = {

688 askUserQuestion?: {

689 previewFormat?: "markdown" | "html";

690 };

691};

692```

693 

694| Field | Type | Description |

695| :------------------------------ | :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

696| `askUserQuestion.previewFormat` | `'markdown' \| 'html'` | Opts into the `preview` field on [`AskUserQuestion`](/en/agent-sdk/user-input#question-format) options and sets its content format. When unset, Claude does not emit previews |

697 

698### `McpServerConfig`

699 

700Configuration for MCP servers.

701 

702```typescript theme={null}

703type McpServerConfig =

704 | McpStdioServerConfig

705 | McpSSEServerConfig

706 | McpHttpServerConfig

707 | McpSdkServerConfigWithInstance;

708```

709 

710#### `McpStdioServerConfig`

711 

712```typescript theme={null}

713type McpStdioServerConfig = {

714 type?: "stdio";

715 command: string;

716 args?: string[];

717 env?: Record<string, string>;

718};

719```

720 

721#### `McpSSEServerConfig`

722 

723```typescript theme={null}

724type McpSSEServerConfig = {

725 type: "sse";

726 url: string;

727 headers?: Record<string, string>;

728};

729```

730 

731#### `McpHttpServerConfig`

732 

733```typescript theme={null}

734type McpHttpServerConfig = {

735 type: "http";

736 url: string;

737 headers?: Record<string, string>;

738};

739```

740 

741#### `McpSdkServerConfigWithInstance`

742 

743```typescript theme={null}

744type McpSdkServerConfigWithInstance = {

745 type: "sdk";

746 name: string;

747 instance: McpServer;

748};

749```

750 

751#### `McpClaudeAIProxyServerConfig`

752 

753```typescript theme={null}

754type McpClaudeAIProxyServerConfig = {

755 type: "claudeai-proxy";

756 url: string;

757 id: string;

758};

759```

760 

761### `SdkPluginConfig`

762 

763Configuration for loading plugins in the SDK.

764 

765```typescript theme={null}

766type SdkPluginConfig = {

767 type: "local";

768 path: string;

769};

770```

771 

772| Field | Type | Description |

773| :----- | :-------- | :--------------------------------------------------------- |

774| `type` | `'local'` | Must be `'local'` (only local plugins currently supported) |

775| `path` | `string` | Absolute or relative path to the plugin directory |

776 

777**Example:**

778 

779```typescript theme={null}

780plugins: [

781 { type: "local", path: "./my-plugin" },

782 { type: "local", path: "/absolute/path/to/plugin" }

783];

784```

785 

786For complete information on creating and using plugins, see [Plugins](/en/agent-sdk/plugins).

787 

788## Message Types

789 

790### `SDKMessage`

791 

792Union type of all possible messages returned by the query.

793 

794```typescript theme={null}

795type SDKMessage =

796 | SDKAssistantMessage

797 | SDKUserMessage

798 | SDKUserMessageReplay

799 | SDKResultMessage

800 | SDKSystemMessage

801 | SDKPartialAssistantMessage

802 | SDKCompactBoundaryMessage

803 | SDKStatusMessage

804 | SDKLocalCommandOutputMessage

805 | SDKHookStartedMessage

806 | SDKHookProgressMessage

807 | SDKHookResponseMessage

808 | SDKPluginInstallMessage

809 | SDKToolProgressMessage

810 | SDKAuthStatusMessage

811 | SDKTaskNotificationMessage

812 | SDKTaskStartedMessage

813 | SDKTaskProgressMessage

814 | SDKTaskUpdatedMessage

815 | SDKFilesPersistedEvent

816 | SDKToolUseSummaryMessage

817 | SDKRateLimitEvent

818 | SDKPromptSuggestionMessage;

819```

820 

821### `SDKAssistantMessage`

822 

823Assistant response message.

824 

825```typescript theme={null}

826type SDKAssistantMessage = {

827 type: "assistant";

828 uuid: UUID;

829 session_id: string;

830 message: BetaMessage; // From Anthropic SDK

831 parent_tool_use_id: string | null;

832 error?: SDKAssistantMessageError;

833};

834```

835 

836The `message` field is a [`BetaMessage`](https://platform.claude.com/docs/en/api/messages/create) from the Anthropic SDK. It includes fields like `id`, `content`, `model`, `stop_reason`, and `usage`.

837 

838`SDKAssistantMessageError` is one of: `'authentication_failed'`, `'billing_error'`, `'rate_limit'`, `'invalid_request'`, `'server_error'`, `'max_output_tokens'`, or `'unknown'`.

839 

840### `SDKUserMessage`

841 

842User input message.

843 

844```typescript theme={null}

845type SDKUserMessage = {

846 type: "user";

847 uuid?: UUID;

848 session_id: string;

849 message: MessageParam; // From Anthropic SDK

850 parent_tool_use_id: string | null;

851 isSynthetic?: boolean;

852 shouldQuery?: boolean;

853 tool_use_result?: unknown;

854};

855```

856 

857Set `shouldQuery` to `false` to append the message to the transcript without triggering an assistant turn. The message is held and merged into the next user message that does trigger a turn. Use this to inject context, such as the output of a command you ran out of band, without spending a model call on it.

858 

859### `SDKUserMessageReplay`

860 

861Replayed user message with required UUID.

862 

863```typescript theme={null}

864type SDKUserMessageReplay = {

865 type: "user";

866 uuid: UUID;

867 session_id: string;

868 message: MessageParam;

869 parent_tool_use_id: string | null;

870 isSynthetic?: boolean;

871 tool_use_result?: unknown;

872 isReplay: true;

873};

874```

875 

876### `SDKResultMessage`

877 

878Final result message.

879 

880```typescript theme={null}

881type SDKResultMessage =

882 | {

883 type: "result";

884 subtype: "success";

885 uuid: UUID;

886 session_id: string;

887 duration_ms: number;

888 duration_api_ms: number;

889 is_error: boolean;

890 num_turns: number;

891 result: string;

892 stop_reason: string | null;

893 total_cost_usd: number;

894 usage: NonNullableUsage;

895 modelUsage: { [modelName: string]: ModelUsage };

896 permission_denials: SDKPermissionDenial[];

897 structured_output?: unknown;

898 deferred_tool_use?: { id: string; name: string; input: Record<string, unknown> };

899 }

900 | {

901 type: "result";

902 subtype:

903 | "error_max_turns"

904 | "error_during_execution"

905 | "error_max_budget_usd"

906 | "error_max_structured_output_retries";

907 uuid: UUID;

908 session_id: string;

909 duration_ms: number;

910 duration_api_ms: number;

911 is_error: boolean;

912 num_turns: number;

913 stop_reason: string | null;

914 total_cost_usd: number;

915 usage: NonNullableUsage;

916 modelUsage: { [modelName: string]: ModelUsage };

917 permission_denials: SDKPermissionDenial[];

918 errors: string[];

919 };

920```

921 

922When a `PreToolUse` hook returns `permissionDecision: "defer"`, the result has `stop_reason: "tool_deferred"` and `deferred_tool_use` carries the pending tool's `id`, `name`, and `input`. Read this field to surface the request in your own UI, then resume with the same `session_id` to continue. See [Defer a tool call for later](/en/hooks#defer-a-tool-call-for-later) for the full round trip.

923 

924### `SDKSystemMessage`

925 

926System initialization message.

927 

928```typescript theme={null}

929type SDKSystemMessage = {

930 type: "system";

931 subtype: "init";

932 uuid: UUID;

933 session_id: string;

934 agents?: string[];

935 apiKeySource: ApiKeySource;

936 betas?: string[];

937 claude_code_version: string;

938 cwd: string;

939 tools: string[];

940 mcp_servers: {

941 name: string;

942 status: string;

943 }[];

944 model: string;

945 permissionMode: PermissionMode;

946 slash_commands: string[];

947 output_style: string;

948 skills: string[];

949 plugins: { name: string; path: string }[];

950};

951```

952 

953### `SDKPartialAssistantMessage`

954 

955Streaming partial message (only when `includePartialMessages` is true).

956 

957```typescript theme={null}

958type SDKPartialAssistantMessage = {

959 type: "stream_event";

960 event: BetaRawMessageStreamEvent; // From Anthropic SDK

961 parent_tool_use_id: string | null;

962 uuid: UUID;

963 session_id: string;

964};

965```

966 

967### `SDKCompactBoundaryMessage`

968 

969Message indicating a conversation compaction boundary.

970 

971```typescript theme={null}

972type SDKCompactBoundaryMessage = {

973 type: "system";

974 subtype: "compact_boundary";

975 uuid: UUID;

976 session_id: string;

977 compact_metadata: {

978 trigger: "manual" | "auto";

979 pre_tokens: number;

980 };

981};

982```

983 

984### `SDKPluginInstallMessage`

985 

986Plugin installation progress event. Emitted when [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](/en/env-vars) is set, so your Agent SDK application can track marketplace plugin installation before the first turn. The `started` and `completed` statuses bracket the overall install. The `installed` and `failed` statuses report individual marketplaces and include `name`.

987 

988```typescript theme={null}

989type SDKPluginInstallMessage = {

990 type: "system";

991 subtype: "plugin_install";

992 status: "started" | "installed" | "failed" | "completed";

993 name?: string;

994 error?: string;

995 uuid: UUID;

996 session_id: string;

997};

998```

999 

1000### `SDKPermissionDenial`

1001 

1002Information about a denied tool use.

1003 

1004```typescript theme={null}

1005type SDKPermissionDenial = {

1006 tool_name: string;

1007 tool_use_id: string;

1008 tool_input: Record<string, unknown>;

1009};

1010```

1011 

1012## Hook Types

1013 

1014For a comprehensive guide on using hooks with examples and common patterns, see the [Hooks guide](/en/agent-sdk/hooks).

1015 

1016### `HookEvent`

1017 

1018Available hook events.

1019 

1020```typescript theme={null}

1021type HookEvent =

1022 | "PreToolUse"

1023 | "PostToolUse"

1024 | "PostToolUseFailure"

1025 | "PostToolBatch"

1026 | "Notification"

1027 | "UserPromptSubmit"

1028 | "SessionStart"

1029 | "SessionEnd"

1030 | "Stop"

1031 | "SubagentStart"

1032 | "SubagentStop"

1033 | "PreCompact"

1034 | "PermissionRequest"

1035 | "Setup"

1036 | "TeammateIdle"

1037 | "TaskCompleted"

1038 | "ConfigChange"

1039 | "WorktreeCreate"

1040 | "WorktreeRemove";

1041```

1042 

1043### `HookCallback`

1044 

1045Hook callback function type.

1046 

1047```typescript theme={null}

1048type HookCallback = (

1049 input: HookInput, // Union of all hook input types

1050 toolUseID: string | undefined,

1051 options: { signal: AbortSignal }

1052) => Promise<HookJSONOutput>;

1053```

1054 

1055### `HookCallbackMatcher`

1056 

1057Hook configuration with optional matcher.

1058 

1059```typescript theme={null}

1060interface HookCallbackMatcher {

1061 matcher?: string;

1062 hooks: HookCallback[];

1063 timeout?: number; // Timeout in seconds for all hooks in this matcher

1064}

1065```

1066 

1067### `HookInput`

1068 

1069Union type of all hook input types.

1070 

1071```typescript theme={null}

1072type HookInput =

1073 | PreToolUseHookInput

1074 | PostToolUseHookInput

1075 | PostToolUseFailureHookInput

1076 | PostToolBatchHookInput

1077 | NotificationHookInput

1078 | UserPromptSubmitHookInput

1079 | SessionStartHookInput

1080 | SessionEndHookInput

1081 | StopHookInput

1082 | SubagentStartHookInput

1083 | SubagentStopHookInput

1084 | PreCompactHookInput

1085 | PermissionRequestHookInput

1086 | SetupHookInput

1087 | TeammateIdleHookInput

1088 | TaskCompletedHookInput

1089 | ConfigChangeHookInput

1090 | WorktreeCreateHookInput

1091 | WorktreeRemoveHookInput;

1092```

1093 

1094### `BaseHookInput`

1095 

1096Base interface that all hook input types extend.

1097 

1098```typescript theme={null}

1099type BaseHookInput = {

1100 session_id: string;

1101 transcript_path: string;

1102 cwd: string;

1103 permission_mode?: string;

1104 agent_id?: string;

1105 agent_type?: string;

1106};

1107```

1108 

1109#### `PreToolUseHookInput`

1110 

1111```typescript theme={null}

1112type PreToolUseHookInput = BaseHookInput & {

1113 hook_event_name: "PreToolUse";

1114 tool_name: string;

1115 tool_input: unknown;

1116 tool_use_id: string;

1117};

1118```

1119 

1120#### `PostToolUseHookInput`

1121 

1122```typescript theme={null}

1123type PostToolUseHookInput = BaseHookInput & {

1124 hook_event_name: "PostToolUse";

1125 tool_name: string;

1126 tool_input: unknown;

1127 tool_response: unknown;

1128 tool_use_id: string;

1129 duration_ms?: number;

1130};

1131```

1132 

1133#### `PostToolUseFailureHookInput`

1134 

1135```typescript theme={null}

1136type PostToolUseFailureHookInput = BaseHookInput & {

1137 hook_event_name: "PostToolUseFailure";

1138 tool_name: string;

1139 tool_input: unknown;

1140 tool_use_id: string;

1141 error: string;

1142 is_interrupt?: boolean;

1143 duration_ms?: number;

1144};

1145```

1146 

1147#### `PostToolBatchHookInput`

1148 

1149Fires once after every tool call in a batch has resolved, before the next model request. `tool_response` carries the serialized `tool_result` content the model sees; the shape differs from `PostToolUseHookInput`'s structured `Output` object.

1150 

1151```typescript theme={null}

1152type PostToolBatchHookInput = BaseHookInput & {

1153 hook_event_name: "PostToolBatch";

1154 tool_calls: PostToolBatchToolCall[];

1155};

1156 

1157type PostToolBatchToolCall = {

1158 tool_name: string;

1159 tool_input: unknown;

1160 tool_use_id: string;

1161 tool_response?: unknown;

1162};

1163```

1164 

1165#### `NotificationHookInput`

1166 

1167```typescript theme={null}

1168type NotificationHookInput = BaseHookInput & {

1169 hook_event_name: "Notification";

1170 message: string;

1171 title?: string;

1172 notification_type: string;

1173};

1174```

1175 

1176#### `UserPromptSubmitHookInput`

1177 

1178```typescript theme={null}

1179type UserPromptSubmitHookInput = BaseHookInput & {

1180 hook_event_name: "UserPromptSubmit";

1181 prompt: string;

1182};

1183```

1184 

1185#### `SessionStartHookInput`

1186 

1187```typescript theme={null}

1188type SessionStartHookInput = BaseHookInput & {

1189 hook_event_name: "SessionStart";

1190 source: "startup" | "resume" | "clear" | "compact";

1191 agent_type?: string;

1192 model?: string;

1193};

1194```

1195 

1196#### `SessionEndHookInput`

1197 

1198```typescript theme={null}

1199type SessionEndHookInput = BaseHookInput & {

1200 hook_event_name: "SessionEnd";

1201 reason: ExitReason; // String from EXIT_REASONS array

1202};

1203```

1204 

1205#### `StopHookInput`

1206 

1207```typescript theme={null}

1208type StopHookInput = BaseHookInput & {

1209 hook_event_name: "Stop";

1210 stop_hook_active: boolean;

1211 last_assistant_message?: string;

1212};

1213```

1214 

1215#### `SubagentStartHookInput`

1216 

1217```typescript theme={null}

1218type SubagentStartHookInput = BaseHookInput & {

1219 hook_event_name: "SubagentStart";

1220 agent_id: string;

1221 agent_type: string;

1222};

1223```

1224 

1225#### `SubagentStopHookInput`

1226 

1227```typescript theme={null}

1228type SubagentStopHookInput = BaseHookInput & {

1229 hook_event_name: "SubagentStop";

1230 stop_hook_active: boolean;

1231 agent_id: string;

1232 agent_transcript_path: string;

1233 agent_type: string;

1234 last_assistant_message?: string;

1235};

1236```

1237 

1238#### `PreCompactHookInput`

1239 

1240```typescript theme={null}

1241type PreCompactHookInput = BaseHookInput & {

1242 hook_event_name: "PreCompact";

1243 trigger: "manual" | "auto";

1244 custom_instructions: string | null;

1245};

1246```

1247 

1248#### `PermissionRequestHookInput`

1249 

1250```typescript theme={null}

1251type PermissionRequestHookInput = BaseHookInput & {

1252 hook_event_name: "PermissionRequest";

1253 tool_name: string;

1254 tool_input: unknown;

1255 permission_suggestions?: PermissionUpdate[];

1256};

1257```

1258 

1259#### `SetupHookInput`

1260 

1261```typescript theme={null}

1262type SetupHookInput = BaseHookInput & {

1263 hook_event_name: "Setup";

1264 trigger: "init" | "maintenance";

1265};

1266```

1267 

1268#### `TeammateIdleHookInput`

1269 

1270```typescript theme={null}

1271type TeammateIdleHookInput = BaseHookInput & {

1272 hook_event_name: "TeammateIdle";

1273 teammate_name: string;

1274 team_name: string;

1275};

1276```

1277 

1278#### `TaskCompletedHookInput`

1279 

1280```typescript theme={null}

1281type TaskCompletedHookInput = BaseHookInput & {

1282 hook_event_name: "TaskCompleted";

1283 task_id: string;

1284 task_subject: string;

1285 task_description?: string;

1286 teammate_name?: string;

1287 team_name?: string;

1288};

1289```

1290 

1291#### `ConfigChangeHookInput`

1292 

1293```typescript theme={null}

1294type ConfigChangeHookInput = BaseHookInput & {

1295 hook_event_name: "ConfigChange";

1296 source:

1297 | "user_settings"

1298 | "project_settings"

1299 | "local_settings"

1300 | "policy_settings"

1301 | "skills";

1302 file_path?: string;

1303};

1304```

1305 

1306#### `WorktreeCreateHookInput`

1307 

1308```typescript theme={null}

1309type WorktreeCreateHookInput = BaseHookInput & {

1310 hook_event_name: "WorktreeCreate";

1311 name: string;

1312};

1313```

1314 

1315#### `WorktreeRemoveHookInput`

1316 

1317```typescript theme={null}

1318type WorktreeRemoveHookInput = BaseHookInput & {

1319 hook_event_name: "WorktreeRemove";

1320 worktree_path: string;

1321};

1322```

1323 

1324### `HookJSONOutput`

1325 

1326Hook return value.

1327 

1328```typescript theme={null}

1329type HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput;

1330```

1331 

1332#### `AsyncHookJSONOutput`

1333 

1334```typescript theme={null}

1335type AsyncHookJSONOutput = {

1336 async: true;

1337 asyncTimeout?: number;

1338};

1339```

1340 

1341#### `SyncHookJSONOutput`

1342 

1343```typescript theme={null}

1344type SyncHookJSONOutput = {

1345 continue?: boolean;

1346 suppressOutput?: boolean;

1347 stopReason?: string;

1348 decision?: "approve" | "block";

1349 systemMessage?: string;

1350 reason?: string;

1351 hookSpecificOutput?:

1352 | {

1353 hookEventName: "PreToolUse";

1354 permissionDecision?: "allow" | "deny" | "ask" | "defer";

1355 permissionDecisionReason?: string;

1356 updatedInput?: Record<string, unknown>;

1357 additionalContext?: string;

1358 }

1359 | {

1360 hookEventName: "UserPromptSubmit";

1361 additionalContext?: string;

1362 }

1363 | {

1364 hookEventName: "SessionStart";

1365 additionalContext?: string;

1366 }

1367 | {

1368 hookEventName: "Setup";

1369 additionalContext?: string;

1370 }

1371 | {

1372 hookEventName: "SubagentStart";

1373 additionalContext?: string;

1374 }

1375 | {

1376 hookEventName: "PostToolUse";

1377 additionalContext?: string;

1378 updatedMCPToolOutput?: unknown;

1379 }

1380 | {

1381 hookEventName: "PostToolUseFailure";

1382 additionalContext?: string;

1383 }

1384 | {

1385 hookEventName: "PostToolBatch";

1386 additionalContext?: string;

1387 }

1388 | {

1389 hookEventName: "Notification";

1390 additionalContext?: string;

1391 }

1392 | {

1393 hookEventName: "PermissionRequest";

1394 decision:

1395 | {

1396 behavior: "allow";

1397 updatedInput?: Record<string, unknown>;

1398 updatedPermissions?: PermissionUpdate[];

1399 }

1400 | {

1401 behavior: "deny";

1402 message?: string;

1403 interrupt?: boolean;

1404 };

1405 };

1406};

1407```

1408 

1409## Tool Input Types

1410 

1411Documentation of input schemas for all built-in Claude Code tools. These types are exported from `@anthropic-ai/claude-agent-sdk` and can be used for type-safe tool interactions.

1412 

1413### `ToolInputSchemas`

1414 

1415Union of all tool input types, exported from `@anthropic-ai/claude-agent-sdk`.

1416 

1417```typescript theme={null}

1418type ToolInputSchemas =

1419 | AgentInput

1420 | AskUserQuestionInput

1421 | BashInput

1422 | TaskOutputInput

1423 | EnterWorktreeInput

1424 | ExitPlanModeInput

1425 | FileEditInput

1426 | FileReadInput

1427 | FileWriteInput

1428 | GlobInput

1429 | GrepInput

1430 | ListMcpResourcesInput

1431 | McpInput

1432 | MonitorInput

1433 | NotebookEditInput

1434 | ReadMcpResourceInput

1435 | SubscribeMcpResourceInput

1436 | SubscribePollingInput

1437 | TaskStopInput

1438 | TodoWriteInput

1439 | UnsubscribeMcpResourceInput

1440 | UnsubscribePollingInput

1441 | WebFetchInput

1442 | WebSearchInput;

1443```

1444 

1445### Agent

1446 

1447**Tool name:** `Agent` (previously `Task`, which is still accepted as an alias)

1448 

1449```typescript theme={null}

1450type AgentInput = {

1451 description: string;

1452 prompt: string;

1453 subagent_type: string;

1454 model?: "sonnet" | "opus" | "haiku";

1455 resume?: string;

1456 run_in_background?: boolean;

1457 max_turns?: number;

1458 name?: string;

1459 team_name?: string;

1460 mode?: "acceptEdits" | "bypassPermissions" | "default" | "dontAsk" | "plan";

1461 isolation?: "worktree";

1462};

1463```

1464 

1465Launches a new agent to handle complex, multi-step tasks autonomously.

1466 

1467### AskUserQuestion

1468 

1469**Tool name:** `AskUserQuestion`

1470 

1471```typescript theme={null}

1472type AskUserQuestionInput = {

1473 questions: Array<{

1474 question: string;

1475 header: string;

1476 options: Array<{ label: string; description: string; preview?: string }>;

1477 multiSelect: boolean;

1478 }>;

1479};

1480```

1481 

1482Asks the user clarifying questions during execution. See [Handle approvals and user input](/en/agent-sdk/user-input#handle-clarifying-questions) for usage details.

1483 

1484### Bash

1485 

1486**Tool name:** `Bash`

1487 

1488```typescript theme={null}

1489type BashInput = {

1490 command: string;

1491 timeout?: number;

1492 description?: string;

1493 run_in_background?: boolean;

1494 dangerouslyDisableSandbox?: boolean;

1495};

1496```

1497 

1498Executes bash commands in a persistent shell session with optional timeout and background execution.

1499 

1500### Monitor

1501 

1502**Tool name:** `Monitor`

1503 

1504```typescript theme={null}

1505type MonitorInput = {

1506 command: string;

1507 description: string;

1508 timeout_ms?: number;

1509 persistent?: boolean;

1510};

1511```

1512 

1513Runs a background script and delivers each stdout line to Claude as an event so it can react without polling. Set `persistent: true` for session-length watches such as log tails. Monitor follows the same permission rules as Bash. See the [Monitor tool reference](/en/tools-reference#monitor-tool) for behavior and provider availability.

1514 

1515### TaskOutput

1516 

1517**Tool name:** `TaskOutput`

1518 

1519```typescript theme={null}

1520type TaskOutputInput = {

1521 task_id: string;

1522 block: boolean;

1523 timeout: number;

1524};

1525```

1526 

1527Retrieves output from a running or completed background task.

1528 

1529### Edit

1530 

1531**Tool name:** `Edit`

1532 

1533```typescript theme={null}

1534type FileEditInput = {

1535 file_path: string;

1536 old_string: string;

1537 new_string: string;

1538 replace_all?: boolean;

1539};

1540```

1541 

1542Performs exact string replacements in files.

1543 

1544### Read

1545 

1546**Tool name:** `Read`

1547 

1548```typescript theme={null}

1549type FileReadInput = {

1550 file_path: string;

1551 offset?: number;

1552 limit?: number;

1553 pages?: string;

1554};

1555```

1556 

1557Reads files from the local filesystem, including text, images, PDFs, and Jupyter notebooks. Use `pages` for PDF page ranges (for example, `"1-5"`).

1558 

1559### Write

1560 

1561**Tool name:** `Write`

1562 

1563```typescript theme={null}

1564type FileWriteInput = {

1565 file_path: string;

1566 content: string;

1567};

1568```

1569 

1570Writes a file to the local filesystem, overwriting if it exists.

1571 

1572### Glob

1573 

1574**Tool name:** `Glob`

1575 

1576```typescript theme={null}

1577type GlobInput = {

1578 pattern: string;

1579 path?: string;

1580};

1581```

1582 

1583Fast file pattern matching that works with any codebase size.

1584 

1585### Grep

1586 

1587**Tool name:** `Grep`

1588 

1589```typescript theme={null}

1590type GrepInput = {

1591 pattern: string;

1592 path?: string;

1593 glob?: string;

1594 type?: string;

1595 output_mode?: "content" | "files_with_matches" | "count";

1596 "-i"?: boolean;

1597 "-n"?: boolean;

1598 "-B"?: number;

1599 "-A"?: number;

1600 "-C"?: number;

1601 context?: number;

1602 head_limit?: number;

1603 offset?: number;

1604 multiline?: boolean;

1605};

1606```

1607 

1608Powerful search tool built on ripgrep with regex support.

1609 

1610### TaskStop

1611 

1612**Tool name:** `TaskStop`

1613 

1614```typescript theme={null}

1615type TaskStopInput = {

1616 task_id?: string;

1617 shell_id?: string; // Deprecated: use task_id

1618};

1619```

1620 

1621Stops a running background task or shell by ID.

1622 

1623### NotebookEdit

1624 

1625**Tool name:** `NotebookEdit`

1626 

1627```typescript theme={null}

1628type NotebookEditInput = {

1629 notebook_path: string;

1630 cell_id?: string;

1631 new_source: string;

1632 cell_type?: "code" | "markdown";

1633 edit_mode?: "replace" | "insert" | "delete";

1634};

1635```

1636 

1637Edits cells in Jupyter notebook files.

1638 

1639### WebFetch

1640 

1641**Tool name:** `WebFetch`

1642 

1643```typescript theme={null}

1644type WebFetchInput = {

1645 url: string;

1646 prompt: string;

1647};

1648```

1649 

1650Fetches content from a URL and processes it with an AI model.

1651 

1652### WebSearch

1653 

1654**Tool name:** `WebSearch`

1655 

1656```typescript theme={null}

1657type WebSearchInput = {

1658 query: string;

1659 allowed_domains?: string[];

1660 blocked_domains?: string[];

1661};

1662```

1663 

1664Searches the web and returns formatted results.

1665 

1666### TodoWrite

1667 

1668**Tool name:** `TodoWrite`

1669 

1670```typescript theme={null}

1671type TodoWriteInput = {

1672 todos: Array<{

1673 content: string;

1674 status: "pending" | "in_progress" | "completed";

1675 activeForm: string;

1676 }>;

1677};

1678```

1679 

1680Creates and manages a structured task list for tracking progress.

1681 

1682### ExitPlanMode

1683 

1684**Tool name:** `ExitPlanMode`

1685 

1686```typescript theme={null}

1687type ExitPlanModeInput = {

1688 allowedPrompts?: Array<{

1689 tool: "Bash";

1690 prompt: string;

1691 }>;

1692};

1693```

1694 

1695Exits planning mode. Optionally specifies prompt-based permissions needed to implement the plan.

1696 

1697### ListMcpResources

1698 

1699**Tool name:** `ListMcpResources`

1700 

1701```typescript theme={null}

1702type ListMcpResourcesInput = {

1703 server?: string;

1704};

1705```

1706 

1707Lists available MCP resources from connected servers.

1708 

1709### ReadMcpResource

1710 

1711**Tool name:** `ReadMcpResource`

1712 

1713```typescript theme={null}

1714type ReadMcpResourceInput = {

1715 server: string;

1716 uri: string;

1717};

1718```

1719 

1720Reads a specific MCP resource from a server.

1721 

1722### EnterWorktree

1723 

1724**Tool name:** `EnterWorktree`

1725 

1726```typescript theme={null}

1727type EnterWorktreeInput = {

1728 name?: string;

1729 path?: string;

1730};

1731```

1732 

1733Creates and enters a temporary git worktree for isolated work. Pass `path` to switch into an existing worktree of the current repository instead of creating a new one. `name` and `path` are mutually exclusive.

1734 

1735## Tool Output Types

1736 

1737Documentation of output schemas for all built-in Claude Code tools. These types are exported from `@anthropic-ai/claude-agent-sdk` and represent the actual response data returned by each tool.

1738 

1739### `ToolOutputSchemas`

1740 

1741Union of all tool output types.

1742 

1743```typescript theme={null}

1744type ToolOutputSchemas =

1745 | AgentOutput

1746 | AskUserQuestionOutput

1747 | BashOutput

1748 | EnterWorktreeOutput

1749 | ExitPlanModeOutput

1750 | FileEditOutput

1751 | FileReadOutput

1752 | FileWriteOutput

1753 | GlobOutput

1754 | GrepOutput

1755 | ListMcpResourcesOutput

1756 | MonitorOutput

1757 | NotebookEditOutput

1758 | ReadMcpResourceOutput

1759 | TaskStopOutput

1760 | TodoWriteOutput

1761 | WebFetchOutput

1762 | WebSearchOutput;

1763```

1764 

1765### Agent

1766 

1767**Tool name:** `Agent` (previously `Task`, which is still accepted as an alias)

1768 

1769```typescript theme={null}

1770type AgentOutput =

1771 | {

1772 status: "completed";

1773 agentId: string;

1774 content: Array<{ type: "text"; text: string }>;

1775 totalToolUseCount: number;

1776 totalDurationMs: number;

1777 totalTokens: number;

1778 usage: {

1779 input_tokens: number;

1780 output_tokens: number;

1781 cache_creation_input_tokens: number | null;

1782 cache_read_input_tokens: number | null;

1783 server_tool_use: {

1784 web_search_requests: number;

1785 web_fetch_requests: number;

1786 } | null;

1787 service_tier: ("standard" | "priority" | "batch") | null;

1788 cache_creation: {

1789 ephemeral_1h_input_tokens: number;

1790 ephemeral_5m_input_tokens: number;

1791 } | null;

1792 };

1793 prompt: string;

1794 }

1795 | {

1796 status: "async_launched";

1797 agentId: string;

1798 description: string;

1799 prompt: string;

1800 outputFile: string;

1801 canReadOutputFile?: boolean;

1802 }

1803 | {

1804 status: "sub_agent_entered";

1805 description: string;

1806 message: string;

1807 };

1808```

1809 

1810Returns the result from the subagent. Discriminated on the `status` field: `"completed"` for finished tasks, `"async_launched"` for background tasks, and `"sub_agent_entered"` for interactive subagents.

1811 

1812### AskUserQuestion

1813 

1814**Tool name:** `AskUserQuestion`

1815 

1816```typescript theme={null}

1817type AskUserQuestionOutput = {

1818 questions: Array<{

1819 question: string;

1820 header: string;

1821 options: Array<{ label: string; description: string; preview?: string }>;

1822 multiSelect: boolean;

1823 }>;

1824 answers: Record<string, string>;

1825};

1826```

1827 

1828Returns the questions asked and the user's answers.

1829 

1830### Bash

1831 

1832**Tool name:** `Bash`

1833 

1834```typescript theme={null}

1835type BashOutput = {

1836 stdout: string;

1837 stderr: string;

1838 rawOutputPath?: string;

1839 interrupted: boolean;

1840 isImage?: boolean;

1841 backgroundTaskId?: string;

1842 backgroundedByUser?: boolean;

1843 dangerouslyDisableSandbox?: boolean;

1844 returnCodeInterpretation?: string;

1845 structuredContent?: unknown[];

1846 persistedOutputPath?: string;

1847 persistedOutputSize?: number;

1848};

1849```

1850 

1851Returns command output with stdout/stderr split. Background commands include a `backgroundTaskId`.

1852 

1853### Monitor

1854 

1855**Tool name:** `Monitor`

1856 

1857```typescript theme={null}

1858type MonitorOutput = {

1859 taskId: string;

1860 timeoutMs: number;

1861 persistent?: boolean;

1862};

1863```

1864 

1865Returns the background task ID for the running monitor. Use this ID with `TaskStop` to cancel the watch early.

1866 

1867### Edit

1868 

1869**Tool name:** `Edit`

1870 

1871```typescript theme={null}

1872type FileEditOutput = {

1873 filePath: string;

1874 oldString: string;

1875 newString: string;

1876 originalFile: string;

1877 structuredPatch: Array<{

1878 oldStart: number;

1879 oldLines: number;

1880 newStart: number;

1881 newLines: number;

1882 lines: string[];

1883 }>;

1884 userModified: boolean;

1885 replaceAll: boolean;

1886 gitDiff?: {

1887 filename: string;

1888 status: "modified" | "added";

1889 additions: number;

1890 deletions: number;

1891 changes: number;

1892 patch: string;

1893 };

1894};

1895```

1896 

1897Returns the structured diff of the edit operation.

1898 

1899### Read

1900 

1901**Tool name:** `Read`

1902 

1903```typescript theme={null}

1904type FileReadOutput =

1905 | {

1906 type: "text";

1907 file: {

1908 filePath: string;

1909 content: string;

1910 numLines: number;

1911 startLine: number;

1912 totalLines: number;

1913 };

1914 }

1915 | {

1916 type: "image";

1917 file: {

1918 base64: string;

1919 type: "image/jpeg" | "image/png" | "image/gif" | "image/webp";

1920 originalSize: number;

1921 dimensions?: {

1922 originalWidth?: number;

1923 originalHeight?: number;

1924 displayWidth?: number;

1925 displayHeight?: number;

1926 };

1927 };

1928 }

1929 | {

1930 type: "notebook";

1931 file: {

1932 filePath: string;

1933 cells: unknown[];

1934 };

1935 }

1936 | {

1937 type: "pdf";

1938 file: {

1939 filePath: string;

1940 base64: string;

1941 originalSize: number;

1942 };

1943 }

1944 | {

1945 type: "parts";

1946 file: {

1947 filePath: string;

1948 originalSize: number;

1949 count: number;

1950 outputDir: string;

1951 };

1952 };

1953```

1954 

1955Returns file contents in a format appropriate to the file type. Discriminated on the `type` field.

1956 

1957### Write

1958 

1959**Tool name:** `Write`

1960 

1961```typescript theme={null}

1962type FileWriteOutput = {

1963 type: "create" | "update";

1964 filePath: string;

1965 content: string;

1966 structuredPatch: Array<{

1967 oldStart: number;

1968 oldLines: number;

1969 newStart: number;

1970 newLines: number;

1971 lines: string[];

1972 }>;

1973 originalFile: string | null;

1974 gitDiff?: {

1975 filename: string;

1976 status: "modified" | "added";

1977 additions: number;

1978 deletions: number;

1979 changes: number;

1980 patch: string;

1981 };

1982};

1983```

1984 

1985Returns the write result with structured diff information.

1986 

1987### Glob

1988 

1989**Tool name:** `Glob`

1990 

1991```typescript theme={null}

1992type GlobOutput = {

1993 durationMs: number;

1994 numFiles: number;

1995 filenames: string[];

1996 truncated: boolean;

1997};

1998```

1999 

2000Returns file paths matching the glob pattern, sorted by modification time.

2001 

2002### Grep

2003 

2004**Tool name:** `Grep`

2005 

2006```typescript theme={null}

2007type GrepOutput = {

2008 mode?: "content" | "files_with_matches" | "count";

2009 numFiles: number;

2010 filenames: string[];

2011 content?: string;

2012 numLines?: number;

2013 numMatches?: number;

2014 appliedLimit?: number;

2015 appliedOffset?: number;

2016};

2017```

2018 

2019Returns search results. The shape varies by `mode`: file list, content with matches, or match counts.

2020 

2021### TaskStop

2022 

2023**Tool name:** `TaskStop`

2024 

2025```typescript theme={null}

2026type TaskStopOutput = {

2027 message: string;

2028 task_id: string;

2029 task_type: string;

2030 command?: string;

2031};

2032```

2033 

2034Returns confirmation after stopping the background task.

2035 

2036### NotebookEdit

2037 

2038**Tool name:** `NotebookEdit`

2039 

2040```typescript theme={null}

2041type NotebookEditOutput = {

2042 new_source: string;

2043 cell_id?: string;

2044 cell_type: "code" | "markdown";

2045 language: string;

2046 edit_mode: string;

2047 error?: string;

2048 notebook_path: string;

2049 original_file: string;

2050 updated_file: string;

2051};

2052```

2053 

2054Returns the result of the notebook edit with original and updated file contents.

2055 

2056### WebFetch

2057 

2058**Tool name:** `WebFetch`

2059 

2060```typescript theme={null}

2061type WebFetchOutput = {

2062 bytes: number;

2063 code: number;

2064 codeText: string;

2065 result: string;

2066 durationMs: number;

2067 url: string;

2068};

2069```

2070 

2071Returns the fetched content with HTTP status and metadata.

2072 

2073### WebSearch

2074 

2075**Tool name:** `WebSearch`

2076 

2077```typescript theme={null}

2078type WebSearchOutput = {

2079 query: string;

2080 results: Array<

2081 | {

2082 tool_use_id: string;

2083 content: Array<{ title: string; url: string }>;

2084 }

2085 | string

2086 >;

2087 durationSeconds: number;

2088};

2089```

2090 

2091Returns search results from the web.

2092 

2093### TodoWrite

2094 

2095**Tool name:** `TodoWrite`

2096 

2097```typescript theme={null}

2098type TodoWriteOutput = {

2099 oldTodos: Array<{

2100 content: string;

2101 status: "pending" | "in_progress" | "completed";

2102 activeForm: string;

2103 }>;

2104 newTodos: Array<{

2105 content: string;

2106 status: "pending" | "in_progress" | "completed";

2107 activeForm: string;

2108 }>;

2109};

2110```

2111 

2112Returns the previous and updated task lists.

2113 

2114### ExitPlanMode

2115 

2116**Tool name:** `ExitPlanMode`

2117 

2118```typescript theme={null}

2119type ExitPlanModeOutput = {

2120 plan: string | null;

2121 isAgent: boolean;

2122 filePath?: string;

2123 hasTaskTool?: boolean;

2124 awaitingLeaderApproval?: boolean;

2125 requestId?: string;

2126};

2127```

2128 

2129Returns the plan state after exiting plan mode.

2130 

2131### ListMcpResources

2132 

2133**Tool name:** `ListMcpResources`

2134 

2135```typescript theme={null}

2136type ListMcpResourcesOutput = Array<{

2137 uri: string;

2138 name: string;

2139 mimeType?: string;

2140 description?: string;

2141 server: string;

2142}>;

2143```

2144 

2145Returns an array of available MCP resources.

2146 

2147### ReadMcpResource

2148 

2149**Tool name:** `ReadMcpResource`

2150 

2151```typescript theme={null}

2152type ReadMcpResourceOutput = {

2153 contents: Array<{

2154 uri: string;

2155 mimeType?: string;

2156 text?: string;

2157 }>;

2158};

2159```

2160 

2161Returns the contents of the requested MCP resource.

2162 

2163### EnterWorktree

2164 

2165**Tool name:** `EnterWorktree`

2166 

2167```typescript theme={null}

2168type EnterWorktreeOutput = {

2169 worktreePath: string;

2170 worktreeBranch?: string;

2171 message: string;

2172};

2173```

2174 

2175Returns information about the git worktree.

2176 

2177## Permission Types

2178 

2179### `PermissionUpdate`

2180 

2181Operations for updating permissions.

2182 

2183```typescript theme={null}

2184type PermissionUpdate =

2185 | {

2186 type: "addRules";

2187 rules: PermissionRuleValue[];

2188 behavior: PermissionBehavior;

2189 destination: PermissionUpdateDestination;

2190 }

2191 | {

2192 type: "replaceRules";

2193 rules: PermissionRuleValue[];

2194 behavior: PermissionBehavior;

2195 destination: PermissionUpdateDestination;

2196 }

2197 | {

2198 type: "removeRules";

2199 rules: PermissionRuleValue[];

2200 behavior: PermissionBehavior;

2201 destination: PermissionUpdateDestination;

2202 }

2203 | {

2204 type: "setMode";

2205 mode: PermissionMode;

2206 destination: PermissionUpdateDestination;

2207 }

2208 | {

2209 type: "addDirectories";

2210 directories: string[];

2211 destination: PermissionUpdateDestination;

2212 }

2213 | {

2214 type: "removeDirectories";

2215 directories: string[];

2216 destination: PermissionUpdateDestination;

2217 };

2218```

2219 

2220### `PermissionBehavior`

2221 

2222```typescript theme={null}

2223type PermissionBehavior = "allow" | "deny" | "ask";

2224```

2225 

2226### `PermissionUpdateDestination`

2227 

2228```typescript theme={null}

2229type PermissionUpdateDestination =

2230 | "userSettings" // Global user settings

2231 | "projectSettings" // Per-directory project settings

2232 | "localSettings" // Gitignored local settings

2233 | "session" // Current session only

2234 | "cliArg"; // CLI argument

2235```

2236 

2237### `PermissionRuleValue`

2238 

2239```typescript theme={null}

2240type PermissionRuleValue = {

2241 toolName: string;

2242 ruleContent?: string;

2243};

2244```

2245 

2246## Other Types

2247 

2248### `ApiKeySource`

2249 

2250```typescript theme={null}

2251type ApiKeySource = "user" | "project" | "org" | "temporary" | "oauth";

2252```

2253 

2254### `SdkBeta`

2255 

2256Available beta features that can be enabled via the `betas` option. See [Beta headers](https://platform.claude.com/docs/en/api/beta-headers) for more information.

2257 

2258```typescript theme={null}

2259type SdkBeta = "context-1m-2025-08-07";

2260```

2261 

2262<Warning>

2263 The `context-1m-2025-08-07` beta is retired as of April 30, 2026. Passing this value with Claude Sonnet 4.5 or Sonnet 4 has no effect, and requests that exceed the standard 200k-token context window return an error. To use a 1M-token context window, migrate to [Claude Sonnet 4.6, Claude Opus 4.6, or Claude Opus 4.7](https://platform.claude.com/docs/en/about-claude/models/overview), which include 1M context at standard pricing with no beta header required.

2264</Warning>

2265 

2266### `SlashCommand`

2267 

2268Information about an available slash command.

2269 

2270```typescript theme={null}

2271type SlashCommand = {

2272 name: string;

2273 description: string;

2274 argumentHint: string;

2275 aliases?: string[];

2276};

2277```

2278 

2279### `ModelInfo`

2280 

2281Information about an available model.

2282 

2283```typescript theme={null}

2284type ModelInfo = {

2285 value: string;

2286 displayName: string;

2287 description: string;

2288 supportsEffort?: boolean;

2289 supportedEffortLevels?: ("low" | "medium" | "high" | "xhigh" | "max")[];

2290 supportsAdaptiveThinking?: boolean;

2291 supportsFastMode?: boolean;

2292};

2293```

2294 

2295### `AgentInfo`

2296 

2297Information about an available subagent that can be invoked via the Agent tool.

2298 

2299```typescript theme={null}

2300type AgentInfo = {

2301 name: string;

2302 description: string;

2303 model?: string;

2304};

2305```

2306 

2307| Field | Type | Description |

2308| :------------ | :-------------------- | :------------------------------------------------------------------- |

2309| `name` | `string` | Agent type identifier (e.g., `"Explore"`, `"general-purpose"`) |

2310| `description` | `string` | Description of when to use this agent |

2311| `model` | `string \| undefined` | Model alias this agent uses. If omitted, inherits the parent's model |

2312 

2313### `McpServerStatus`

2314 

2315Status of a connected MCP server.

2316 

2317```typescript theme={null}

2318type McpServerStatus = {

2319 name: string;

2320 status: "connected" | "failed" | "needs-auth" | "pending" | "disabled";

2321 serverInfo?: {

2322 name: string;

2323 version: string;

2324 };

2325 error?: string;

2326 config?: McpServerStatusConfig;

2327 scope?: string;

2328 tools?: {

2329 name: string;

2330 description?: string;

2331 annotations?: {

2332 readOnly?: boolean;

2333 destructive?: boolean;

2334 openWorld?: boolean;

2335 };

2336 }[];

2337};

2338```

2339 

2340### `McpServerStatusConfig`

2341 

2342The configuration of an MCP server as reported by `mcpServerStatus()`. This is the union of all MCP server transport types.

2343 

2344```typescript theme={null}

2345type McpServerStatusConfig =

2346 | McpStdioServerConfig

2347 | McpSSEServerConfig

2348 | McpHttpServerConfig

2349 | McpSdkServerConfig

2350 | McpClaudeAIProxyServerConfig;

2351```

2352 

2353See [`McpServerConfig`](#mcp-server-config) for details on each transport type.

2354 

2355### `AccountInfo`

2356 

2357Account information for the authenticated user.

2358 

2359```typescript theme={null}

2360type AccountInfo = {

2361 email?: string;

2362 organization?: string;

2363 subscriptionType?: string;

2364 tokenSource?: string;

2365 apiKeySource?: string;

2366};

2367```

2368 

2369### `ModelUsage`

2370 

2371Per-model usage statistics returned in result messages. The `costUSD` value is a client-side estimate. See [Track cost and usage](/en/agent-sdk/cost-tracking) for billing caveats.

2372 

2373```typescript theme={null}

2374type ModelUsage = {

2375 inputTokens: number;

2376 outputTokens: number;

2377 cacheReadInputTokens: number;

2378 cacheCreationInputTokens: number;

2379 webSearchRequests: number;

2380 costUSD: number;

2381 contextWindow: number;

2382 maxOutputTokens: number;

2383};

2384```

2385 

2386### `ConfigScope`

2387 

2388```typescript theme={null}

2389type ConfigScope = "local" | "user" | "project";

2390```

2391 

2392### `NonNullableUsage`

2393 

2394A version of [`Usage`](#usage) with all nullable fields made non-nullable.

2395 

2396```typescript theme={null}

2397type NonNullableUsage = {

2398 [K in keyof Usage]: NonNullable<Usage[K]>;

2399};

2400```

2401 

2402### `Usage`

2403 

2404Token usage statistics (from `@anthropic-ai/sdk`).

2405 

2406```typescript theme={null}

2407type Usage = {

2408 input_tokens: number | null;

2409 output_tokens: number | null;

2410 cache_creation_input_tokens?: number | null;

2411 cache_read_input_tokens?: number | null;

2412};

2413```

2414 

2415### `CallToolResult`

2416 

2417MCP tool result type (from `@modelcontextprotocol/sdk/types.js`).

2418 

2419```typescript theme={null}

2420type CallToolResult = {

2421 content: Array<{

2422 type: "text" | "image" | "resource";

2423 // Additional fields vary by type

2424 }>;

2425 isError?: boolean;

2426};

2427```

2428 

2429### `ThinkingConfig`

2430 

2431Controls Claude's thinking/reasoning behavior. Takes precedence over the deprecated `maxThinkingTokens`.

2432 

2433```typescript theme={null}

2434type ThinkingConfig =

2435 | { type: "adaptive" } // The model determines when and how much to reason (Opus 4.6+)

2436 | { type: "enabled"; budgetTokens?: number } // Fixed thinking token budget

2437 | { type: "disabled" }; // No extended thinking

2438```

2439 

2440### `SpawnedProcess`

2441 

2442Interface for custom process spawning (used with `spawnClaudeCodeProcess` option). `ChildProcess` already satisfies this interface.

2443 

2444```typescript theme={null}

2445interface SpawnedProcess {

2446 stdin: Writable;

2447 stdout: Readable;

2448 readonly killed: boolean;

2449 readonly exitCode: number | null;

2450 kill(signal: NodeJS.Signals): boolean;

2451 on(

2452 event: "exit",

2453 listener: (code: number | null, signal: NodeJS.Signals | null) => void

2454 ): void;

2455 on(event: "error", listener: (error: Error) => void): void;

2456 once(

2457 event: "exit",

2458 listener: (code: number | null, signal: NodeJS.Signals | null) => void

2459 ): void;

2460 once(event: "error", listener: (error: Error) => void): void;

2461 off(

2462 event: "exit",

2463 listener: (code: number | null, signal: NodeJS.Signals | null) => void

2464 ): void;

2465 off(event: "error", listener: (error: Error) => void): void;

2466}

2467```

2468 

2469### `SpawnOptions`

2470 

2471Options passed to the custom spawn function.

2472 

2473```typescript theme={null}

2474interface SpawnOptions {

2475 command: string;

2476 args: string[];

2477 cwd?: string;

2478 env: Record<string, string | undefined>;

2479 signal: AbortSignal;

2480}

2481```

2482 

2483### `McpSetServersResult`

2484 

2485Result of a `setMcpServers()` operation.

2486 

2487```typescript theme={null}

2488type McpSetServersResult = {

2489 added: string[];

2490 removed: string[];

2491 errors: Record<string, string>;

2492};

2493```

2494 

2495### `RewindFilesResult`

2496 

2497Result of a `rewindFiles()` operation.

2498 

2499```typescript theme={null}

2500type RewindFilesResult = {

2501 canRewind: boolean;

2502 error?: string;

2503 filesChanged?: string[];

2504 insertions?: number;

2505 deletions?: number;

2506};

2507```

2508 

2509### `SDKStatusMessage`

2510 

2511Status update message (e.g., compacting).

2512 

2513```typescript theme={null}

2514type SDKStatusMessage = {

2515 type: "system";

2516 subtype: "status";

2517 status: "compacting" | null;

2518 permissionMode?: PermissionMode;

2519 uuid: UUID;

2520 session_id: string;

2521};

2522```

2523 

2524### `SDKTaskNotificationMessage`

2525 

2526Notification when a background task completes, fails, or is stopped. Background tasks include `run_in_background` Bash commands, [Monitor](#monitor) watches, and background subagents.

2527 

2528```typescript theme={null}

2529type SDKTaskNotificationMessage = {

2530 type: "system";

2531 subtype: "task_notification";

2532 task_id: string;

2533 tool_use_id?: string;

2534 status: "completed" | "failed" | "stopped";

2535 output_file: string;

2536 summary: string;

2537 usage?: {

2538 total_tokens: number;

2539 tool_uses: number;

2540 duration_ms: number;

2541 };

2542 uuid: UUID;

2543 session_id: string;

2544};

2545```

2546 

2547### `SDKToolUseSummaryMessage`

2548 

2549Summary of tool usage in a conversation.

2550 

2551```typescript theme={null}

2552type SDKToolUseSummaryMessage = {

2553 type: "tool_use_summary";

2554 summary: string;

2555 preceding_tool_use_ids: string[];

2556 uuid: UUID;

2557 session_id: string;

2558};

2559```

2560 

2561### `SDKHookStartedMessage`

2562 

2563Emitted when a hook begins executing.

2564 

2565```typescript theme={null}

2566type SDKHookStartedMessage = {

2567 type: "system";

2568 subtype: "hook_started";

2569 hook_id: string;

2570 hook_name: string;

2571 hook_event: string;

2572 uuid: UUID;

2573 session_id: string;

2574};

2575```

2576 

2577### `SDKHookProgressMessage`

2578 

2579Emitted while a hook is running, with stdout/stderr output.

2580 

2581```typescript theme={null}

2582type SDKHookProgressMessage = {

2583 type: "system";

2584 subtype: "hook_progress";

2585 hook_id: string;

2586 hook_name: string;

2587 hook_event: string;

2588 stdout: string;

2589 stderr: string;

2590 output: string;

2591 uuid: UUID;

2592 session_id: string;

2593};

2594```

2595 

2596### `SDKHookResponseMessage`

2597 

2598Emitted when a hook finishes executing.

2599 

2600```typescript theme={null}

2601type SDKHookResponseMessage = {

2602 type: "system";

2603 subtype: "hook_response";

2604 hook_id: string;

2605 hook_name: string;

2606 hook_event: string;

2607 output: string;

2608 stdout: string;

2609 stderr: string;

2610 exit_code?: number;

2611 outcome: "success" | "error" | "cancelled";

2612 uuid: UUID;

2613 session_id: string;

2614};

2615```

2616 

2617### `SDKToolProgressMessage`

2618 

2619Emitted periodically while a tool is executing to indicate progress.

2620 

2621```typescript theme={null}

2622type SDKToolProgressMessage = {

2623 type: "tool_progress";

2624 tool_use_id: string;

2625 tool_name: string;

2626 parent_tool_use_id: string | null;

2627 elapsed_time_seconds: number;

2628 task_id?: string;

2629 uuid: UUID;

2630 session_id: string;

2631};

2632```

2633 

2634### `SDKAuthStatusMessage`

2635 

2636Emitted during authentication flows.

2637 

2638```typescript theme={null}

2639type SDKAuthStatusMessage = {

2640 type: "auth_status";

2641 isAuthenticating: boolean;

2642 output: string[];

2643 error?: string;

2644 uuid: UUID;

2645 session_id: string;

2646};

2647```

2648 

2649### `SDKTaskStartedMessage`

2650 

2651Emitted when a background task begins. The `task_type` field is `"local_bash"` for background Bash commands and [Monitor](#monitor) watches, `"local_agent"` for subagents, or `"remote_agent"`.

2652 

2653```typescript theme={null}

2654type SDKTaskStartedMessage = {

2655 type: "system";

2656 subtype: "task_started";

2657 task_id: string;

2658 tool_use_id?: string;

2659 description: string;

2660 task_type?: string;

2661 uuid: UUID;

2662 session_id: string;

2663};

2664```

2665 

2666### `SDKTaskProgressMessage`

2667 

2668Emitted periodically while a background task is running.

2669 

2670```typescript theme={null}

2671type SDKTaskProgressMessage = {

2672 type: "system";

2673 subtype: "task_progress";

2674 task_id: string;

2675 tool_use_id?: string;

2676 description: string;

2677 usage: {

2678 total_tokens: number;

2679 tool_uses: number;

2680 duration_ms: number;

2681 };

2682 last_tool_name?: string;

2683 uuid: UUID;

2684 session_id: string;

2685};

2686```

2687 

2688### `SDKTaskUpdatedMessage`

2689 

2690Emitted when a background task's state changes, such as when it transitions from `running` to `completed`. Merge `patch` into your local task map keyed by `task_id`. The `end_time` field is a Unix epoch timestamp in milliseconds, comparable with `Date.now()`.

2691 

2692```typescript theme={null}

2693type SDKTaskUpdatedMessage = {

2694 type: "system";

2695 subtype: "task_updated";

2696 task_id: string;

2697 patch: {

2698 status?: "pending" | "running" | "completed" | "failed" | "killed";

2699 description?: string;

2700 end_time?: number;

2701 total_paused_ms?: number;

2702 error?: string;

2703 is_backgrounded?: boolean;

2704 };

2705 uuid: UUID;

2706 session_id: string;

2707};

2708```

2709 

2710### `SDKFilesPersistedEvent`

2711 

2712Emitted when file checkpoints are persisted to disk.

2713 

2714```typescript theme={null}

2715type SDKFilesPersistedEvent = {

2716 type: "system";

2717 subtype: "files_persisted";

2718 files: { filename: string; file_id: string }[];

2719 failed: { filename: string; error: string }[];

2720 processed_at: string;

2721 uuid: UUID;

2722 session_id: string;

2723};

2724```

2725 

2726### `SDKRateLimitEvent`

2727 

2728Emitted when the session encounters a rate limit.

2729 

2730```typescript theme={null}

2731type SDKRateLimitEvent = {

2732 type: "rate_limit_event";

2733 rate_limit_info: {

2734 status: "allowed" | "allowed_warning" | "rejected";

2735 resetsAt?: number;

2736 utilization?: number;

2737 };

2738 uuid: UUID;

2739 session_id: string;

2740};

2741```

2742 

2743### `SDKLocalCommandOutputMessage`

2744 

2745Output from a local slash command (for example, `/voice` or `/usage`). Displayed as assistant-style text in the transcript.

2746 

2747```typescript theme={null}

2748type SDKLocalCommandOutputMessage = {

2749 type: "system";

2750 subtype: "local_command_output";

2751 content: string;

2752 uuid: UUID;

2753 session_id: string;

2754};

2755```

2756 

2757### `SDKPromptSuggestionMessage`

2758 

2759Emitted after each turn when `promptSuggestions` is enabled. Contains a predicted next user prompt.

2760 

2761```typescript theme={null}

2762type SDKPromptSuggestionMessage = {

2763 type: "prompt_suggestion";

2764 suggestion: string;

2765 uuid: UUID;

2766 session_id: string;

2767};

2768```

2769 

2770### `AbortError`

2771 

2772Custom error class for abort operations.

2773 

2774```typescript theme={null}

2775class AbortError extends Error {}

2776```

2777 

2778## Sandbox Configuration

2779 

2780### `SandboxSettings`

2781 

2782Configuration for sandbox behavior. Use this to enable command sandboxing and configure network restrictions programmatically.

2783 

2784```typescript theme={null}

2785type SandboxSettings = {

2786 enabled?: boolean;

2787 autoAllowBashIfSandboxed?: boolean;

2788 excludedCommands?: string[];

2789 allowUnsandboxedCommands?: boolean;

2790 network?: SandboxNetworkConfig;

2791 filesystem?: SandboxFilesystemConfig;

2792 ignoreViolations?: Record<string, string[]>;

2793 enableWeakerNestedSandbox?: boolean;

2794 ripgrep?: { command: string; args?: string[] };

2795};

2796```

2797 

2798| Property | Type | Default | Description |

2799| :-------------------------- | :------------------------------------------------------ | :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

2800| `enabled` | `boolean` | `false` | Enable sandbox mode for command execution |

2801| `autoAllowBashIfSandboxed` | `boolean` | `true` | Auto-approve bash commands when sandbox is enabled |

2802| `excludedCommands` | `string[]` | `[]` | Commands that always bypass sandbox restrictions (e.g., `['docker']`). These run unsandboxed automatically without model involvement |

2803| `allowUnsandboxedCommands` | `boolean` | `true` | Allow the model to request running commands outside the sandbox. When `true`, the model can set `dangerouslyDisableSandbox` in tool input, which falls back to the [permissions system](#permissions-fallback-for-unsandboxed-commands) |

2804| `network` | [`SandboxNetworkConfig`](#sandbox-network-config) | `undefined` | Network-specific sandbox configuration |

2805| `filesystem` | [`SandboxFilesystemConfig`](#sandbox-filesystem-config) | `undefined` | Filesystem-specific sandbox configuration for read/write restrictions |

2806| `ignoreViolations` | `Record<string, string[]>` | `undefined` | Map of violation categories to patterns to ignore (e.g., `{ file: ['/tmp/*'], network: ['localhost'] }`) |

2807| `enableWeakerNestedSandbox` | `boolean` | `false` | Enable a weaker nested sandbox for compatibility |

2808| `ripgrep` | `{ command: string; args?: string[] }` | `undefined` | Custom ripgrep binary configuration for sandbox environments |

2809 

2810#### Example usage

2811 

2812```typescript theme={null}

2813import { query } from "@anthropic-ai/claude-agent-sdk";

2814 

2815for await (const message of query({

2816 prompt: "Build and test my project",

2817 options: {

2818 sandbox: {

2819 enabled: true,

2820 autoAllowBashIfSandboxed: true,

2821 network: {

2822 allowLocalBinding: true

2823 }

2824 }

2825 }

2826})) {

2827 if ("result" in message) console.log(message.result);

2828}

2829```

2830 

2831<Warning>

2832 **Unix socket security:** The `allowUnixSockets` option can grant access to powerful system services. For example, allowing `/var/run/docker.sock` effectively grants full host system access through the Docker API, bypassing sandbox isolation. Only allow Unix sockets that are strictly necessary and understand the security implications of each.

2833</Warning>

2834 

2835### `SandboxNetworkConfig`

2836 

2837Network-specific configuration for sandbox mode.

2838 

2839```typescript theme={null}

2840type SandboxNetworkConfig = {

2841 allowedDomains?: string[];

2842 deniedDomains?: string[];

2843 allowManagedDomainsOnly?: boolean;

2844 allowLocalBinding?: boolean;

2845 allowUnixSockets?: string[];

2846 allowAllUnixSockets?: boolean;

2847 httpProxyPort?: number;

2848 socksProxyPort?: number;

2849};

2850```

2851 

2852| Property | Type | Default | Description |

2853| :------------------------ | :--------- | :---------- | :------------------------------------------------------------------------------------------ |

2854| `allowedDomains` | `string[]` | `[]` | Domain names that sandboxed processes can access |

2855| `deniedDomains` | `string[]` | `[]` | Domain names that sandboxed processes cannot access. Takes precedence over `allowedDomains` |

2856| `allowManagedDomainsOnly` | `boolean` | `false` | Restrict network access to only the domains in `allowedDomains` |

2857| `allowLocalBinding` | `boolean` | `false` | Allow processes to bind to local ports (e.g., for dev servers) |

2858| `allowUnixSockets` | `string[]` | `[]` | Unix socket paths that processes can access (e.g., Docker socket) |

2859| `allowAllUnixSockets` | `boolean` | `false` | Allow access to all Unix sockets |

2860| `httpProxyPort` | `number` | `undefined` | HTTP proxy port for network requests |

2861| `socksProxyPort` | `number` | `undefined` | SOCKS proxy port for network requests |

2862 

2863### `SandboxFilesystemConfig`

2864 

2865Filesystem-specific configuration for sandbox mode.

2866 

2867```typescript theme={null}

2868type SandboxFilesystemConfig = {

2869 allowWrite?: string[];

2870 denyWrite?: string[];

2871 denyRead?: string[];

2872};

2873```

2874 

2875| Property | Type | Default | Description |

2876| :----------- | :--------- | :------ | :------------------------------------------ |

2877| `allowWrite` | `string[]` | `[]` | File path patterns to allow write access to |

2878| `denyWrite` | `string[]` | `[]` | File path patterns to deny write access to |

2879| `denyRead` | `string[]` | `[]` | File path patterns to deny read access to |

2880 

2881### Permissions Fallback for Unsandboxed Commands

2882 

2883When `allowUnsandboxedCommands` is enabled, the model can request to run commands outside the sandbox by setting `dangerouslyDisableSandbox: true` in the tool input. These requests fall back to the existing permissions system, meaning your `canUseTool` handler is invoked, allowing you to implement custom authorization logic.

2884 

2885<Note>

2886 **`excludedCommands` vs `allowUnsandboxedCommands`:**

2887 

2888 * `excludedCommands`: A static list of commands that always bypass the sandbox automatically (e.g., `['docker']`). The model has no control over this.

2889 * `allowUnsandboxedCommands`: Lets the model decide at runtime whether to request unsandboxed execution by setting `dangerouslyDisableSandbox: true` in the tool input.

2890</Note>

2891 

2892```typescript theme={null}

2893import { query } from "@anthropic-ai/claude-agent-sdk";

2894 

2895for await (const message of query({

2896 prompt: "Deploy my application",

2897 options: {

2898 sandbox: {

2899 enabled: true,

2900 allowUnsandboxedCommands: true // Model can request unsandboxed execution

2901 },

2902 permissionMode: "default",

2903 canUseTool: async (tool, input) => {

2904 // Check if the model is requesting to bypass the sandbox

2905 if (tool === "Bash" && input.dangerouslyDisableSandbox) {

2906 // The model is requesting to run this command outside the sandbox

2907 console.log(`Unsandboxed command requested: ${input.command}`);

2908 

2909 if (isCommandAuthorized(input.command)) {

2910 return { behavior: "allow" as const, updatedInput: input };

2911 }

2912 return {

2913 behavior: "deny" as const,

2914 message: "Command not authorized for unsandboxed execution"

2915 };

2916 }

2917 return { behavior: "allow" as const, updatedInput: input };

2918 }

2919 }

2920})) {

2921 if ("result" in message) console.log(message.result);

2922}

2923```

2924 

2925This pattern enables you to:

2926 

2927* **Audit model requests:** Log when the model requests unsandboxed execution

2928* **Implement allowlists:** Only permit specific commands to run unsandboxed

2929* **Add approval workflows:** Require explicit authorization for privileged operations

2930 

2931<Warning>

2932 Commands running with `dangerouslyDisableSandbox: true` have full system access. Ensure your `canUseTool` handler validates these requests carefully.

2933 

2934 If `permissionMode` is set to `bypassPermissions` and `allowUnsandboxedCommands` is enabled, the model can autonomously execute commands outside the sandbox without any approval prompts. This combination effectively allows the model to escape sandbox isolation silently.

2935</Warning>

2936 

2937## See also

2938 

2939* [SDK overview](/en/agent-sdk/overview) - General SDK concepts

2940* [Python SDK reference](/en/agent-sdk/python) - Python SDK documentation

2941* [CLI reference](/en/cli-reference) - Command-line interface

2942* [Common workflows](/en/common-workflows) - Step-by-step guides

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# TypeScript SDK V2 interface (preview)

6 

7> Preview of the simplified V2 TypeScript Agent SDK, with session-based send/stream patterns for multi-turn conversations.

8 

9<Warning>

10 The V2 interface is an **unstable preview**. APIs may change based on feedback before becoming stable. Some features like session forking are only available in the [V1 SDK](/en/agent-sdk/typescript).

11</Warning>

12 

13The V2 Claude Agent TypeScript SDK removes the need for async generators and yield coordination. This makes multi-turn conversations simpler, instead of managing generator state across turns, each turn is a separate `send()`/`stream()` cycle. The API surface reduces to three concepts:

14 

15* `createSession()` / `resumeSession()`: Start or continue a conversation

16* `session.send()`: Send a message

17* `session.stream()`: Get the response

18 

19## Installation

20 

21The V2 interface is included in the existing SDK package:

22 

23```bash theme={null}

24npm install @anthropic-ai/claude-agent-sdk

25```

26 

27<Note>

28 The SDK bundles a native Claude Code binary for your platform as an optional dependency, so you don't need to install Claude Code separately.

29</Note>

30 

31## Quick start

32 

33### One-shot prompt

34 

35For simple single-turn queries where you don't need to maintain a session, use `unstable_v2_prompt()`. This example sends a math question and logs the answer:

36 

37```typescript theme={null}

38import { unstable_v2_prompt } from "@anthropic-ai/claude-agent-sdk";

39 

40const result = await unstable_v2_prompt("What is 2 + 2?", {

41 model: "claude-opus-4-7"

42});

43if (result.subtype === "success") {

44 console.log(result.result);

45}

46```

47 

48<details>

49 <summary>See the same operation in V1</summary>

50 

51 ```typescript theme={null}

52 import { query } from "@anthropic-ai/claude-agent-sdk";

53 

54 const q = query({

55 prompt: "What is 2 + 2?",

56 options: { model: "claude-opus-4-7" }

57 });

58 

59 for await (const msg of q) {

60 if (msg.type === "result" && msg.subtype === "success") {

61 console.log(msg.result);

62 }

63 }

64 ```

65</details>

66 

67### Basic session

68 

69For interactions beyond a single prompt, create a session. V2 separates sending and streaming into distinct steps:

70 

71* `send()` dispatches your message

72* `stream()` streams back the response

73 

74This explicit separation makes it easier to add logic between turns (like processing responses before sending follow-ups).

75 

76The example below creates a session, sends "Hello!" to Claude, and prints the text response. It uses [`await using`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management) (TypeScript 5.2+) to automatically close the session when the block exits. You can also call `session.close()` manually.

77 

78```typescript theme={null}

79import { unstable_v2_createSession } from "@anthropic-ai/claude-agent-sdk";

80 

81await using session = unstable_v2_createSession({

82 model: "claude-opus-4-7"

83});

84 

85await session.send("Hello!");

86for await (const msg of session.stream()) {

87 // Filter for assistant messages to get human-readable output

88 if (msg.type === "assistant") {

89 const text = msg.message.content

90 .filter((block) => block.type === "text")

91 .map((block) => block.text)

92 .join("");

93 console.log(text);

94 }

95}

96```

97 

98<details>

99 <summary>See the same operation in V1</summary>

100 

101 In V1, both input and output flow through a single async generator. For a basic prompt this looks similar, but adding multi-turn logic requires restructuring to use an input generator.

102 

103 ```typescript theme={null}

104 import { query } from "@anthropic-ai/claude-agent-sdk";

105 

106 const q = query({

107 prompt: "Hello!",

108 options: { model: "claude-opus-4-7" }

109 });

110 

111 for await (const msg of q) {

112 if (msg.type === "assistant") {

113 const text = msg.message.content

114 .filter((block) => block.type === "text")

115 .map((block) => block.text)

116 .join("");

117 console.log(text);

118 }

119 }

120 ```

121</details>

122 

123### Multi-turn conversation

124 

125Sessions persist context across multiple exchanges. To continue a conversation, call `send()` again on the same session. Claude remembers the previous turns.

126 

127This example asks a math question, then asks a follow-up that references the previous answer:

128 

129```typescript theme={null}

130import { unstable_v2_createSession } from "@anthropic-ai/claude-agent-sdk";

131 

132await using session = unstable_v2_createSession({

133 model: "claude-opus-4-7"

134});

135 

136// Turn 1

137await session.send("What is 5 + 3?");

138for await (const msg of session.stream()) {

139 // Filter for assistant messages to get human-readable output

140 if (msg.type === "assistant") {

141 const text = msg.message.content

142 .filter((block) => block.type === "text")

143 .map((block) => block.text)

144 .join("");

145 console.log(text);

146 }

147}

148 

149// Turn 2

150await session.send("Multiply that by 2");

151for await (const msg of session.stream()) {

152 if (msg.type === "assistant") {

153 const text = msg.message.content

154 .filter((block) => block.type === "text")

155 .map((block) => block.text)

156 .join("");

157 console.log(text);

158 }

159}

160```

161 

162<details>

163 <summary>See the same operation in V1</summary>

164 

165 ```typescript theme={null}

166 import { query } from "@anthropic-ai/claude-agent-sdk";

167 

168 // Must create an async iterable to feed messages

169 async function* createInputStream() {

170 yield {

171 type: "user",

172 session_id: "",

173 message: { role: "user", content: [{ type: "text", text: "What is 5 + 3?" }] },

174 parent_tool_use_id: null

175 };

176 // Must coordinate when to yield next message

177 yield {

178 type: "user",

179 session_id: "",

180 message: { role: "user", content: [{ type: "text", text: "Multiply by 2" }] },

181 parent_tool_use_id: null

182 };

183 }

184 

185 const q = query({

186 prompt: createInputStream(),

187 options: { model: "claude-opus-4-7" }

188 });

189 

190 for await (const msg of q) {

191 if (msg.type === "assistant") {

192 const text = msg.message.content

193 .filter((block) => block.type === "text")

194 .map((block) => block.text)

195 .join("");

196 console.log(text);

197 }

198 }

199 ```

200</details>

201 

202### Session resume

203 

204If you have a session ID from a previous interaction, you can resume it later. This is useful for long-running workflows or when you need to persist conversations across application restarts.

205 

206This example creates a session, stores its ID, closes it, then resumes the conversation:

207 

208```typescript theme={null}

209import {

210 unstable_v2_createSession,

211 unstable_v2_resumeSession,

212 type SDKMessage

213} from "@anthropic-ai/claude-agent-sdk";

214 

215// Helper to extract text from assistant messages

216function getAssistantText(msg: SDKMessage): string | null {

217 if (msg.type !== "assistant") return null;

218 return msg.message.content

219 .filter((block) => block.type === "text")

220 .map((block) => block.text)

221 .join("");

222}

223 

224// Create initial session and have a conversation

225const session = unstable_v2_createSession({

226 model: "claude-opus-4-7"

227});

228 

229await session.send("Remember this number: 42");

230 

231// Get the session ID from any received message

232let sessionId: string | undefined;

233for await (const msg of session.stream()) {

234 sessionId = msg.session_id;

235 const text = getAssistantText(msg);

236 if (text) console.log("Initial response:", text);

237}

238 

239console.log("Session ID:", sessionId);

240session.close();

241 

242// Later: resume the session using the stored ID

243await using resumedSession = unstable_v2_resumeSession(sessionId!, {

244 model: "claude-opus-4-7"

245});

246 

247await resumedSession.send("What number did I ask you to remember?");

248for await (const msg of resumedSession.stream()) {

249 const text = getAssistantText(msg);

250 if (text) console.log("Resumed response:", text);

251}

252```

253 

254<details>

255 <summary>See the same operation in V1</summary>

256 

257 ```typescript theme={null}

258 import { query } from "@anthropic-ai/claude-agent-sdk";

259 

260 // Create initial session

261 const initialQuery = query({

262 prompt: "Remember this number: 42",

263 options: { model: "claude-opus-4-7" }

264 });

265 

266 // Get session ID from any message

267 let sessionId: string | undefined;

268 for await (const msg of initialQuery) {

269 sessionId = msg.session_id;

270 if (msg.type === "assistant") {

271 const text = msg.message.content

272 .filter((block) => block.type === "text")

273 .map((block) => block.text)

274 .join("");

275 console.log("Initial response:", text);

276 }

277 }

278 

279 console.log("Session ID:", sessionId);

280 

281 // Later: resume the session

282 const resumedQuery = query({

283 prompt: "What number did I ask you to remember?",

284 options: {

285 model: "claude-opus-4-7",

286 resume: sessionId

287 }

288 });

289 

290 for await (const msg of resumedQuery) {

291 if (msg.type === "assistant") {

292 const text = msg.message.content

293 .filter((block) => block.type === "text")

294 .map((block) => block.text)

295 .join("");

296 console.log("Resumed response:", text);

297 }

298 }

299 ```

300</details>

301 

302### Cleanup

303 

304Sessions can be closed manually or automatically using [`await using`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management), a TypeScript 5.2+ feature for automatic resource cleanup. If you're using an older TypeScript version or encounter compatibility issues, use manual cleanup instead.

305 

306**Automatic cleanup (TypeScript 5.2+):**

307 

308```typescript theme={null}

309import { unstable_v2_createSession } from "@anthropic-ai/claude-agent-sdk";

310 

311await using session = unstable_v2_createSession({

312 model: "claude-opus-4-7"

313});

314// Session closes automatically when the block exits

315```

316 

317**Manual cleanup:**

318 

319```typescript theme={null}

320import { unstable_v2_createSession } from "@anthropic-ai/claude-agent-sdk";

321 

322const session = unstable_v2_createSession({

323 model: "claude-opus-4-7"

324});

325// ... use the session ...

326session.close();

327```

328 

329## API reference

330 

331### `unstable_v2_createSession()`

332 

333Creates a new session for multi-turn conversations.

334 

335```typescript theme={null}

336function unstable_v2_createSession(options: {

337 model: string;

338 // Additional options supported

339}): SDKSession;

340```

341 

342### `unstable_v2_resumeSession()`

343 

344Resumes an existing session by ID.

345 

346```typescript theme={null}

347function unstable_v2_resumeSession(

348 sessionId: string,

349 options: {

350 model: string;

351 // Additional options supported

352 }

353): SDKSession;

354```

355 

356### `unstable_v2_prompt()`

357 

358One-shot convenience function for single-turn queries.

359 

360```typescript theme={null}

361function unstable_v2_prompt(

362 prompt: string,

363 options: {

364 model: string;

365 // Additional options supported

366 }

367): Promise<SDKResultMessage>;

368```

369 

370### SDKSession interface

371 

372```typescript theme={null}

373interface SDKSession {

374 readonly sessionId: string;

375 send(message: string | SDKUserMessage): Promise<void>;

376 stream(): AsyncGenerator<SDKMessage, void>;

377 close(): void;

378}

379```

380 

381## Feature availability

382 

383Not all V1 features are available in V2 yet. The following require using the [V1 SDK](/en/agent-sdk/typescript):

384 

385* Session forking (`forkSession` option)

386* Some advanced streaming input patterns

387 

388## Feedback

389 

390Share your feedback on the V2 interface before it becomes stable. Report issues and suggestions through [GitHub Issues](https://github.com/anthropics/claude-code/issues).

391 

392## See also

393 

394* [TypeScript SDK reference (V1)](/en/agent-sdk/typescript) - Full V1 SDK documentation

395* [SDK overview](/en/agent-sdk/overview) - General SDK concepts

396* [V2 examples on GitHub](https://github.com/anthropics/claude-agent-sdk-demos/tree/main/hello-world-v2) - Working code examples

agent-sdk/user-input.md +810 −0 added

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# Handle approvals and user input

6 

7> Surface Claude's approval requests and clarifying questions to users, then return their decisions to the SDK.

8 

9While working on a task, Claude sometimes needs to check in with users. It might need permission before deleting files, or need to ask which database to use for a new project. Your application needs to surface these requests to users so Claude can continue with their input.

10 

11Claude requests user input in two situations: when it needs **permission to use a tool** (like deleting files or running commands), and when it has **clarifying questions** (via the `AskUserQuestion` tool). Both trigger your `canUseTool` callback, which pauses execution until you return a response. This is different from normal conversation turns where Claude finishes and waits for your next message.

12 

13For clarifying questions, Claude generates the questions and options. Your role is to present them to users and return their selections. You can't add your own questions to this flow; if you need to ask users something yourself, do that separately in your application logic.

14 

15The callback can stay pending indefinitely. Execution remains paused until your callback returns, and the SDK only cancels the wait when the query itself is cancelled. If a user might take longer to respond than your process can reasonably stay running, the TypeScript SDK supports the [`defer` hook decision](/en/hooks#defer-a-tool-call-for-later), which lets the process exit and resume later from the persisted session; this option is not available in the Python SDK.

16 

17This guide shows you how to detect each type of request and respond appropriately.

18 

19## Detect when Claude needs input

20 

21Pass a `canUseTool` callback in your query options. The callback fires whenever Claude needs user input, receiving the tool name and input as arguments:

22 

23<CodeGroup>

24 ```python Python theme={null}

25 async def handle_tool_request(tool_name, input_data, context):

26 # Prompt user and return allow or deny

27 ...

28 

29 

30 options = ClaudeAgentOptions(can_use_tool=handle_tool_request)

31 ```

32 

33 ```typescript TypeScript theme={null}

34 async function handleToolRequest(toolName, input, options) {

35 // options includes { signal: AbortSignal, suggestions?: PermissionUpdate[] }

36 // Prompt user and return allow or deny

37 }

38 

39 const options = { canUseTool: handleToolRequest };

40 ```

41</CodeGroup>

42 

43The callback fires in two cases:

44 

451. **Tool needs approval**: Claude wants to use a tool that isn't auto-approved by [permission rules](/en/agent-sdk/permissions) or modes. Check `tool_name` for the tool (e.g., `"Bash"`, `"Write"`).

462. **Claude asks a question**: Claude calls the `AskUserQuestion` tool. Check if `tool_name == "AskUserQuestion"` to handle it differently. If you specify a `tools` array, include `AskUserQuestion` for this to work. See [Handle clarifying questions](#handle-clarifying-questions) for details.

47 

48<Note>

49 To automatically allow or deny tools without prompting users, use [hooks](/en/agent-sdk/hooks) instead. Hooks execute before `canUseTool` and can allow, deny, or modify requests based on your own logic. You can also use the [`PermissionRequest` hook](/en/agent-sdk/hooks#available-hooks) to send external notifications (Slack, email, push) when Claude is waiting for approval.

50</Note>

51 

52## Handle tool approval requests

53 

54Once you've passed a `canUseTool` callback in your query options, it fires when Claude wants to use a tool that isn't auto-approved. Your callback receives three arguments:

55 

56| Argument | Description |

57| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

58| `toolName` | The name of the tool Claude wants to use (e.g., `"Bash"`, `"Write"`, `"Edit"`) |

59| `input` | The parameters Claude is passing to the tool. Contents vary by tool. |

60| `options` (TS) / `context` (Python) | Additional context including optional `suggestions` (proposed `PermissionUpdate` entries to avoid re-prompting) and a cancellation signal. In TypeScript, `signal` is an `AbortSignal`; in Python, the signal field is reserved for future use. See [`ToolPermissionContext`](/en/agent-sdk/python#tool-permission-context) for Python. |

61 

62The `input` object contains tool-specific parameters. Common examples:

63 

64| Tool | Input fields |

65| ------- | --------------------------------------- |

66| `Bash` | `command`, `description`, `timeout` |

67| `Write` | `file_path`, `content` |

68| `Edit` | `file_path`, `old_string`, `new_string` |

69| `Read` | `file_path`, `offset`, `limit` |

70 

71See the SDK reference for complete input schemas: [Python](/en/agent-sdk/python#tool-input-output-types) | [TypeScript](/en/agent-sdk/typescript#tool-input-types).

72 

73You can display this information to the user so they can decide whether to allow or reject the action, then return the appropriate response.

74 

75The following example asks Claude to create and delete a test file. When Claude attempts each operation, the callback prints the tool request to the terminal and prompts for y/n approval.

76 

77<CodeGroup>

78 ```python Python theme={null}

79 import asyncio

80 

81 from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query

82 from claude_agent_sdk.types import (

83 HookMatcher,

84 PermissionResultAllow,

85 PermissionResultDeny,

86 ToolPermissionContext,

87 )

88 

89 

90 async def can_use_tool(

91 tool_name: str, input_data: dict, context: ToolPermissionContext

92 ) -> PermissionResultAllow | PermissionResultDeny:

93 # Display the tool request

94 print(f"\nTool: {tool_name}")

95 if tool_name == "Bash":

96 print(f"Command: {input_data.get('command')}")

97 if input_data.get("description"):

98 print(f"Description: {input_data.get('description')}")

99 else:

100 print(f"Input: {input_data}")

101 

102 # Get user approval

103 response = input("Allow this action? (y/n): ")

104 

105 # Return allow or deny based on user's response

106 if response.lower() == "y":

107 # Allow: tool executes with the original (or modified) input

108 return PermissionResultAllow(updated_input=input_data)

109 else:

110 # Deny: tool doesn't execute, Claude sees the message

111 return PermissionResultDeny(message="User denied this action")

112 

113 

114 # Required workaround: dummy hook keeps the stream open for can_use_tool

115 async def dummy_hook(input_data, tool_use_id, context):

116 return {"continue_": True}

117 

118 

119 async def prompt_stream():

120 yield {

121 "type": "user",

122 "message": {

123 "role": "user",

124 "content": "Create a test file in /tmp and then delete it",

125 },

126 }

127 

128 

129 async def main():

130 async for message in query(

131 prompt=prompt_stream(),

132 options=ClaudeAgentOptions(

133 can_use_tool=can_use_tool,

134 hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},

135 ),

136 ):

137 if isinstance(message, ResultMessage) and message.subtype == "success":

138 print(message.result)

139 

140 

141 asyncio.run(main())

142 ```

143 

144 ```typescript TypeScript theme={null}

145 import { query } from "@anthropic-ai/claude-agent-sdk";

146 import * as readline from "readline";

147 

148 // Helper to prompt user for input in the terminal

149 function prompt(question: string): Promise<string> {

150 const rl = readline.createInterface({

151 input: process.stdin,

152 output: process.stdout

153 });

154 return new Promise((resolve) =>

155 rl.question(question, (answer) => {

156 rl.close();

157 resolve(answer);

158 })

159 );

160 }

161 

162 for await (const message of query({

163 prompt: "Create a test file in /tmp and then delete it",

164 options: {

165 canUseTool: async (toolName, input) => {

166 // Display the tool request

167 console.log(`\nTool: ${toolName}`);

168 if (toolName === "Bash") {

169 console.log(`Command: ${input.command}`);

170 if (input.description) console.log(`Description: ${input.description}`);

171 } else {

172 console.log(`Input: ${JSON.stringify(input, null, 2)}`);

173 }

174 

175 // Get user approval

176 const response = await prompt("Allow this action? (y/n): ");

177 

178 // Return allow or deny based on user's response

179 if (response.toLowerCase() === "y") {

180 // Allow: tool executes with the original (or modified) input

181 return { behavior: "allow", updatedInput: input };

182 } else {

183 // Deny: tool doesn't execute, Claude sees the message

184 return { behavior: "deny", message: "User denied this action" };

185 }

186 }

187 }

188 })) {

189 if ("result" in message) console.log(message.result);

190 }

191 ```

192</CodeGroup>

193 

194<Note>

195 In Python, `can_use_tool` requires [streaming mode](/en/agent-sdk/streaming-vs-single-mode) and a `PreToolUse` hook that returns `{"continue_": True}` to keep the stream open. Without this hook, the stream closes before the permission callback can be invoked.

196</Note>

197 

198This example uses a `y/n` flow where any input other than `y` is treated as a denial. In practice, you might build a richer UI that lets users modify the request, provide feedback, or redirect Claude entirely. See [Respond to tool requests](#respond-to-tool-requests) for all the ways you can respond.

199 

200### Respond to tool requests

201 

202Your callback returns one of two response types:

203 

204| Response | Python | TypeScript |

205| --------- | ------------------------------------------ | ------------------------------------- |

206| **Allow** | `PermissionResultAllow(updated_input=...)` | `{ behavior: "allow", updatedInput }` |

207| **Deny** | `PermissionResultDeny(message=...)` | `{ behavior: "deny", message }` |

208 

209When allowing, pass the tool input (original or modified). When denying, provide a message explaining why. Claude sees this message and may adjust its approach.

210 

211<CodeGroup>

212 ```python Python theme={null}

213 from claude_agent_sdk.types import PermissionResultAllow, PermissionResultDeny

214 

215 # Allow the tool to execute

216 return PermissionResultAllow(updated_input=input_data)

217 

218 # Block the tool

219 return PermissionResultDeny(message="User rejected this action")

220 ```

221 

222 ```typescript TypeScript theme={null}

223 // Allow the tool to execute

224 return { behavior: "allow", updatedInput: input };

225 

226 // Block the tool

227 return { behavior: "deny", message: "User rejected this action" };

228 ```

229</CodeGroup>

230 

231Beyond allowing or denying, you can modify the tool's input or provide context that helps Claude adjust its approach:

232 

233* **Approve**: let the tool execute as Claude requested

234* **Approve with changes**: modify the input before execution (e.g., sanitize paths, add constraints)

235* **Reject**: block the tool and tell Claude why

236* **Suggest alternative**: block but guide Claude toward what the user wants instead

237* **Redirect entirely**: use [streaming input](/en/agent-sdk/streaming-vs-single-mode) to send Claude a completely new instruction

238 

239<Tabs>

240 <Tab title="Approve">

241 The user approves the action as-is. Pass through the `input` from your callback unchanged and the tool executes exactly as Claude requested.

242 

243 <CodeGroup>

244 ```python Python theme={null}

245 async def can_use_tool(tool_name, input_data, context):

246 print(f"Claude wants to use {tool_name}")

247 approved = await ask_user("Allow this action?")

248 

249 if approved:

250 return PermissionResultAllow(updated_input=input_data)

251 return PermissionResultDeny(message="User declined")

252 ```

253 

254 ```typescript TypeScript theme={null}

255 canUseTool: async (toolName, input) => {

256 console.log(`Claude wants to use ${toolName}`);

257 const approved = await askUser("Allow this action?");

258 

259 if (approved) {

260 return { behavior: "allow", updatedInput: input };

261 }

262 return { behavior: "deny", message: "User declined" };

263 };

264 ```

265 </CodeGroup>

266 </Tab>

267 

268 <Tab title="Approve with changes">

269 The user approves but wants to modify the request first. You can change the input before the tool executes. Claude sees the result but isn't told you changed anything. Useful for sanitizing parameters, adding constraints, or scoping access.

270 

271 <CodeGroup>

272 ```python Python theme={null}

273 async def can_use_tool(tool_name, input_data, context):

274 if tool_name == "Bash":

275 # User approved, but scope all commands to sandbox

276 sandboxed_input = {**input_data}

277 sandboxed_input["command"] = input_data["command"].replace(

278 "/tmp", "/tmp/sandbox"

279 )

280 return PermissionResultAllow(updated_input=sandboxed_input)

281 return PermissionResultAllow(updated_input=input_data)

282 ```

283 

284 ```typescript TypeScript theme={null}

285 canUseTool: async (toolName, input) => {

286 if (toolName === "Bash") {

287 // User approved, but scope all commands to sandbox

288 const sandboxedInput = {

289 ...input,

290 command: input.command.replace("/tmp", "/tmp/sandbox")

291 };

292 return { behavior: "allow", updatedInput: sandboxedInput };

293 }

294 return { behavior: "allow", updatedInput: input };

295 };

296 ```

297 </CodeGroup>

298 </Tab>

299 

300 <Tab title="Reject">

301 The user doesn't want this action to happen. Block the tool and provide a message explaining why. Claude sees this message and may try a different approach.

302 

303 <CodeGroup>

304 ```python Python theme={null}

305 async def can_use_tool(tool_name, input_data, context):

306 approved = await ask_user(f"Allow {tool_name}?")

307 

308 if not approved:

309 return PermissionResultDeny(message="User rejected this action")

310 return PermissionResultAllow(updated_input=input_data)

311 ```

312 

313 ```typescript TypeScript theme={null}

314 canUseTool: async (toolName, input) => {

315 const approved = await askUser(`Allow ${toolName}?`);

316 

317 if (!approved) {

318 return {

319 behavior: "deny",

320 message: "User rejected this action"

321 };

322 }

323 return { behavior: "allow", updatedInput: input };

324 };

325 ```

326 </CodeGroup>

327 </Tab>

328 

329 <Tab title="Suggest alternative">

330 The user doesn't want this specific action, but has a different idea. Block the tool and include guidance in your message. Claude will read this and decide how to proceed based on your feedback.

331 

332 <CodeGroup>

333 ```python Python theme={null}

334 async def can_use_tool(tool_name, input_data, context):

335 if tool_name == "Bash" and "rm" in input_data.get("command", ""):

336 # User doesn't want to delete, suggest archiving instead

337 return PermissionResultDeny(

338 message="User doesn't want to delete files. They asked if you could compress them into an archive instead."

339 )

340 return PermissionResultAllow(updated_input=input_data)

341 ```

342 

343 ```typescript TypeScript theme={null}

344 canUseTool: async (toolName, input) => {

345 if (toolName === "Bash" && input.command.includes("rm")) {

346 // User doesn't want to delete, suggest archiving instead

347 return {

348 behavior: "deny",

349 message:

350 "User doesn't want to delete files. They asked if you could compress them into an archive instead."

351 };

352 }

353 return { behavior: "allow", updatedInput: input };

354 };

355 ```

356 </CodeGroup>

357 </Tab>

358 

359 <Tab title="Redirect entirely">

360 For a complete change of direction (not just a nudge), use [streaming input](/en/agent-sdk/streaming-vs-single-mode) to send Claude a new instruction directly. This bypasses the current tool request and gives Claude entirely new instructions to follow.

361 </Tab>

362</Tabs>

363 

364## Handle clarifying questions

365 

366When Claude needs more direction on a task with multiple valid approaches, it calls the `AskUserQuestion` tool. This triggers your `canUseTool` callback with `toolName` set to `AskUserQuestion`. The input contains Claude's questions as multiple-choice options, which you display to the user and return their selections.

367 

368<Tip>

369 Clarifying questions are especially common in [`plan` mode](/en/agent-sdk/permissions#plan-mode-plan), where Claude explores the codebase and asks questions before proposing a plan. This makes plan mode ideal for interactive workflows where you want Claude to gather requirements before making changes.

370</Tip>

371 

372The following steps show how to handle clarifying questions:

373 

374<Steps>

375 <Step title="Pass a canUseTool callback">

376 Pass a `canUseTool` callback in your query options. By default, `AskUserQuestion` is available. If you specify a `tools` array to restrict Claude's capabilities (for example, a read-only agent with only `Read`, `Glob`, and `Grep`), include `AskUserQuestion` in that array. Otherwise, Claude won't be able to ask clarifying questions:

377 

378 <CodeGroup>

379 ```python Python theme={null}

380 async for message in query(

381 prompt="Analyze this codebase",

382 options=ClaudeAgentOptions(

383 # Include AskUserQuestion in your tools list

384 tools=["Read", "Glob", "Grep", "AskUserQuestion"],

385 can_use_tool=can_use_tool,

386 ),

387 ):

388 print(message)

389 ```

390 

391 ```typescript TypeScript theme={null}

392 for await (const message of query({

393 prompt: "Analyze this codebase",

394 options: {

395 // Include AskUserQuestion in your tools list

396 tools: ["Read", "Glob", "Grep", "AskUserQuestion"],

397 canUseTool: async (toolName, input) => {

398 // Handle clarifying questions here

399 }

400 }

401 })) {

402 console.log(message);

403 }

404 ```

405 </CodeGroup>

406 </Step>

407 

408 <Step title="Detect AskUserQuestion">

409 In your callback, check if `toolName` equals `AskUserQuestion` to handle it differently from other tools:

410 

411 <CodeGroup>

412 ```python Python theme={null}

413 async def can_use_tool(tool_name: str, input_data: dict, context):

414 if tool_name == "AskUserQuestion":

415 # Your implementation to collect answers from the user

416 return await handle_clarifying_questions(input_data)

417 # Handle other tools normally

418 return await prompt_for_approval(tool_name, input_data)

419 ```

420 

421 ```typescript TypeScript theme={null}

422 canUseTool: async (toolName, input) => {

423 if (toolName === "AskUserQuestion") {

424 // Your implementation to collect answers from the user

425 return handleClarifyingQuestions(input);

426 }

427 // Handle other tools normally

428 return promptForApproval(toolName, input);

429 };

430 ```

431 </CodeGroup>

432 </Step>

433 

434 <Step title="Parse the question input">

435 The input contains Claude's questions in a `questions` array. Each question has a `question` (the text to display), `options` (the choices), and `multiSelect` (whether multiple selections are allowed):

436 

437 ```json theme={null}

438 {

439 "questions": [

440 {

441 "question": "How should I format the output?",

442 "header": "Format",

443 "options": [

444 { "label": "Summary", "description": "Brief overview" },

445 { "label": "Detailed", "description": "Full explanation" }

446 ],

447 "multiSelect": false

448 },

449 {

450 "question": "Which sections should I include?",

451 "header": "Sections",

452 "options": [

453 { "label": "Introduction", "description": "Opening context" },

454 { "label": "Conclusion", "description": "Final summary" }

455 ],

456 "multiSelect": true

457 }

458 ]

459 }

460 ```

461 

462 See [Question format](#question-format) for full field descriptions.

463 </Step>

464 

465 <Step title="Collect answers from the user">

466 Present the questions to the user and collect their selections. How you do this depends on your application: a terminal prompt, a web form, a mobile dialog, etc.

467 </Step>

468 

469 <Step title="Return answers to Claude">

470 Build the `answers` object as a record where each key is the `question` text and each value is the selected option's `label`:

471 

472 | From the question object | Use as |

473 | ------------------------------------------------------------ | ------ |

474 | `question` field (e.g., `"How should I format the output?"`) | Key |

475 | Selected option's `label` field (e.g., `"Summary"`) | Value |

476 

477 For multi-select questions, join multiple labels with `", "`. If you [support free-text input](#support-free-text-input), use the user's custom text as the value.

478 

479 <CodeGroup>

480 ```python Python theme={null}

481 return PermissionResultAllow(

482 updated_input={

483 "questions": input_data.get("questions", []),

484 "answers": {

485 "How should I format the output?": "Summary",

486 "Which sections should I include?": "Introduction, Conclusion",

487 },

488 }

489 )

490 ```

491 

492 ```typescript TypeScript theme={null}

493 return {

494 behavior: "allow",

495 updatedInput: {

496 questions: input.questions,

497 answers: {

498 "How should I format the output?": "Summary",

499 "Which sections should I include?": "Introduction, Conclusion"

500 }

501 }

502 };

503 ```

504 </CodeGroup>

505 </Step>

506</Steps>

507 

508### Question format

509 

510The input contains Claude's generated questions in a `questions` array. Each question has these fields:

511 

512| Field | Description |

513| ------------- | --------------------------------------------------------------------------------------------------------------------------------------- |

514| `question` | The full question text to display |

515| `header` | Short label for the question (max 12 characters) |

516| `options` | Array of 2-4 choices, each with `label` and `description`. TypeScript: optionally `preview` (see [below](#option-previews-type-script)) |

517| `multiSelect` | If `true`, users can select multiple options |

518 

519The structure your callback receives:

520 

521```json theme={null}

522{

523 "questions": [

524 {

525 "question": "How should I format the output?",

526 "header": "Format",

527 "options": [

528 { "label": "Summary", "description": "Brief overview of key points" },

529 { "label": "Detailed", "description": "Full explanation with examples" }

530 ],

531 "multiSelect": false

532 }

533 ]

534}

535```

536 

537#### Option previews (TypeScript)

538 

539`toolConfig.askUserQuestion.previewFormat` adds a `preview` field to each option so your app can show a visual mockup alongside the label. Without this setting, Claude does not generate previews and the field is absent.

540 

541| `previewFormat` | `preview` contains |

542| :-------------- | :------------------------------------------------------------------------------------------------------------ |

543| unset (default) | Field is absent. Claude does not generate previews. |

544| `"markdown"` | ASCII art and fenced code blocks |

545| `"html"` | A styled `<div>` fragment (the SDK rejects `<script>`, `<style>`, and `<!DOCTYPE>` before your callback runs) |

546 

547The format applies to all questions in the session. Claude includes `preview` on options where a visual comparison helps (layout choices, color schemes) and omits it where one wouldn't (yes/no confirmations, text-only choices). Check for `undefined` before rendering.

548 

549```typescript theme={null}

550import { query } from "@anthropic-ai/claude-agent-sdk";

551 

552for await (const message of query({

553 prompt: "Help me choose a card layout",

554 options: {

555 toolConfig: {

556 askUserQuestion: { previewFormat: "html" }

557 },

558 canUseTool: async (toolName, input) => {

559 // input.questions[].options[].preview is an HTML string or undefined

560 return { behavior: "allow", updatedInput: input };

561 }

562 }

563})) {

564 // ...

565}

566```

567 

568An option with an HTML preview:

569 

570```json theme={null}

571{

572 "label": "Compact",

573 "description": "Title and metric value only",

574 "preview": "<div style=\"padding:12px;border:1px solid #ddd;border-radius:8px\"><div style=\"font-size:12px;color:#666\">Active users</div><div style=\"font-size:28px;font-weight:600\">1,284</div></div>"

575}

576```

577 

578### Response format

579 

580Return an `answers` object mapping each question's `question` field to the selected option's `label`:

581 

582| Field | Description |

583| ----------- | ------------------------------------------------------------------------ |

584| `questions` | Pass through the original questions array (required for tool processing) |

585| `answers` | Object where keys are question text and values are selected labels |

586 

587For multi-select questions, join multiple labels with `", "`. For free-text input, use the user's custom text directly.

588 

589```json theme={null}

590{

591 "questions": [

592 // ...

593 ],

594 "answers": {

595 "How should I format the output?": "Summary",

596 "Which sections should I include?": "Introduction, Conclusion"

597 }

598}

599```

600 

601#### Support free-text input

602 

603Claude's predefined options won't always cover what users want. To let users type their own answer:

604 

605* Display an additional "Other" choice after Claude's options that accepts text input

606* Use the user's custom text as the answer value (not the word "Other")

607 

608See the [complete example](#complete-example) below for a full implementation.

609 

610### Complete example

611 

612Claude asks clarifying questions when it needs user input to proceed. For example, when asked to help decide on a tech stack for a mobile app, Claude might ask about cross-platform vs native, backend preferences, or target platforms. These questions help Claude make decisions that match the user's preferences rather than guessing.

613 

614This example handles those questions in a terminal application. Here's what happens at each step:

615 

6161. **Route the request**: The `canUseTool` callback checks if the tool name is `"AskUserQuestion"` and routes to a dedicated handler

6172. **Display questions**: The handler loops through the `questions` array and prints each question with numbered options

6183. **Collect input**: The user can enter a number to select an option, or type free text directly (e.g., "jquery", "i don't know")

6194. **Map answers**: The code checks if input is numeric (uses the option's label) or free text (uses the text directly)

6205. **Return to Claude**: The response includes both the original `questions` array and the `answers` mapping

621 

622<CodeGroup>

623 ```python Python theme={null}

624 import asyncio

625 

626 from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query

627 from claude_agent_sdk.types import HookMatcher, PermissionResultAllow

628 

629 

630 def parse_response(response: str, options: list) -> str:

631 """Parse user input as option number(s) or free text."""

632 try:

633 indices = [int(s.strip()) - 1 for s in response.split(",")]

634 labels = [options[i]["label"] for i in indices if 0 <= i < len(options)]

635 return ", ".join(labels) if labels else response

636 except ValueError:

637 return response

638 

639 

640 async def handle_ask_user_question(input_data: dict) -> PermissionResultAllow:

641 """Display Claude's questions and collect user answers."""

642 answers = {}

643 

644 for q in input_data.get("questions", []):

645 print(f"\n{q['header']}: {q['question']}")

646 

647 options = q["options"]

648 for i, opt in enumerate(options):

649 print(f" {i + 1}. {opt['label']} - {opt['description']}")

650 if q.get("multiSelect"):

651 print(" (Enter numbers separated by commas, or type your own answer)")

652 else:

653 print(" (Enter a number, or type your own answer)")

654 

655 response = input("Your choice: ").strip()

656 answers[q["question"]] = parse_response(response, options)

657 

658 return PermissionResultAllow(

659 updated_input={

660 "questions": input_data.get("questions", []),

661 "answers": answers,

662 }

663 )

664 

665 

666 async def can_use_tool(

667 tool_name: str, input_data: dict, context

668 ) -> PermissionResultAllow:

669 # Route AskUserQuestion to our question handler

670 if tool_name == "AskUserQuestion":

671 return await handle_ask_user_question(input_data)

672 # Auto-approve other tools for this example

673 return PermissionResultAllow(updated_input=input_data)

674 

675 

676 async def prompt_stream():

677 yield {

678 "type": "user",

679 "message": {

680 "role": "user",

681 "content": "Help me decide on the tech stack for a new mobile app",

682 },

683 }

684 

685 

686 # Required workaround: dummy hook keeps the stream open for can_use_tool

687 async def dummy_hook(input_data, tool_use_id, context):

688 return {"continue_": True}

689 

690 

691 async def main():

692 async for message in query(

693 prompt=prompt_stream(),

694 options=ClaudeAgentOptions(

695 can_use_tool=can_use_tool,

696 hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},

697 ),

698 ):

699 if isinstance(message, ResultMessage) and message.subtype == "success":

700 print(message.result)

701 

702 

703 asyncio.run(main())

704 ```

705 

706 ```typescript TypeScript theme={null}

707 import { query } from "@anthropic-ai/claude-agent-sdk";

708 import * as readline from "readline/promises";

709 

710 // Helper to prompt user for input in the terminal

711 async function prompt(question: string): Promise<string> {

712 const rl = readline.createInterface({ input: process.stdin, output: process.stdout });

713 const answer = await rl.question(question);

714 rl.close();

715 return answer;

716 }

717 

718 // Parse user input as option number(s) or free text

719 function parseResponse(response: string, options: any[]): string {

720 const indices = response.split(",").map((s) => parseInt(s.trim()) - 1);

721 const labels = indices

722 .filter((i) => !isNaN(i) && i >= 0 && i < options.length)

723 .map((i) => options[i].label);

724 return labels.length > 0 ? labels.join(", ") : response;

725 }

726 

727 // Display Claude's questions and collect user answers

728 async function handleAskUserQuestion(input: any) {

729 const answers: Record<string, string> = {};

730 

731 for (const q of input.questions) {

732 console.log(`\n${q.header}: ${q.question}`);

733 

734 const options = q.options;

735 options.forEach((opt: any, i: number) => {

736 console.log(` ${i + 1}. ${opt.label} - ${opt.description}`);

737 });

738 if (q.multiSelect) {

739 console.log(" (Enter numbers separated by commas, or type your own answer)");

740 } else {

741 console.log(" (Enter a number, or type your own answer)");

742 }

743 

744 const response = (await prompt("Your choice: ")).trim();

745 answers[q.question] = parseResponse(response, options);

746 }

747 

748 // Return the answers to Claude (must include original questions)

749 return {

750 behavior: "allow",

751 updatedInput: { questions: input.questions, answers }

752 };

753 }

754 

755 async function main() {

756 for await (const message of query({

757 prompt: "Help me decide on the tech stack for a new mobile app",

758 options: {

759 canUseTool: async (toolName, input) => {

760 // Route AskUserQuestion to our question handler

761 if (toolName === "AskUserQuestion") {

762 return handleAskUserQuestion(input);

763 }

764 // Auto-approve other tools for this example

765 return { behavior: "allow", updatedInput: input };

766 }

767 }

768 })) {

769 if ("result" in message) console.log(message.result);

770 }

771 }

772 

773 main();

774 ```

775</CodeGroup>

776 

777## Limitations

778 

779* **Subagents**: `AskUserQuestion` is not currently available in subagents spawned via the Agent tool

780* **Question limits**: each `AskUserQuestion` call supports 1-4 questions with 2-4 options each

781 

782## Other ways to get user input

783 

784The `canUseTool` callback and `AskUserQuestion` tool cover most approval and clarification scenarios, but the SDK offers other ways to get input from users:

785 

786### Streaming input

787 

788Use [streaming input](/en/agent-sdk/streaming-vs-single-mode) when you need to:

789 

790* **Interrupt the agent mid-task**: send a cancel signal or change direction while Claude is working

791* **Provide additional context**: add information Claude needs without waiting for it to ask

792* **Build chat interfaces**: let users send follow-up messages during long-running operations

793 

794Streaming input is ideal for conversational UIs where users interact with the agent throughout execution, not just at approval checkpoints.

795 

796### Custom tools

797 

798Use [custom tools](/en/agent-sdk/custom-tools) when you need to:

799 

800* **Collect structured input**: build forms, wizards, or multi-step workflows that go beyond `AskUserQuestion`'s multiple-choice format

801* **Integrate external approval systems**: connect to existing ticketing, workflow, or approval platforms

802* **Implement domain-specific interactions**: create tools tailored to your application's needs, like code review interfaces or deployment checklists

803 

804Custom tools give you full control over the interaction, but require more implementation work than using the built-in `canUseTool` callback.

805 

806## Related resources

807 

808* [Configure permissions](/en/agent-sdk/permissions): set up permission modes and rules

809* [Control execution with hooks](/en/agent-sdk/hooks): run custom code at key points in the agent lifecycle

810* [TypeScript SDK reference](/en/agent-sdk/typescript#can-use-tool): full canUseTool API documentation

agent-teams.md +424 −0 added

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# Orchestrate teams of Claude Code sessions

6 

7> Coordinate multiple Claude Code instances working together as a team, with shared tasks, inter-agent messaging, and centralized management.

8 

9<Warning>

10 Agent teams are experimental and disabled by default. Enable them by adding `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` to your [settings.json](/en/settings) or environment. Agent teams have [known limitations](#limitations) around session resumption, task coordination, and shutdown behavior.

11</Warning>

12 

13Agent teams let you coordinate multiple Claude Code instances working together. One session acts as the team lead, coordinating work, assigning tasks, and synthesizing results. Teammates work independently, each in its own context window, and communicate directly with each other.

14 

15Unlike [subagents](/en/sub-agents), which run within a single session and can only report back to the main agent, you can also interact with individual teammates directly without going through the lead.

16 

17<Note>

18 Agent teams require Claude Code v2.1.32 or later. Check your version with `claude --version`.

19</Note>

20 

21This page covers:

22 

23* [When to use agent teams](#when-to-use-agent-teams), including best use cases and how they compare with subagents

24* [Starting a team](#start-your-first-agent-team)

25* [Controlling teammates](#control-your-agent-team), including display modes, task assignment, and delegation

26* [Best practices for parallel work](#best-practices)

27 

28## When to use agent teams

29 

30Agent teams are most effective for tasks where parallel exploration adds real value. See [use case examples](#use-case-examples) for full scenarios. The strongest use cases are:

31 

32* **Research and review**: multiple teammates can investigate different aspects of a problem simultaneously, then share and challenge each other's findings

33* **New modules or features**: teammates can each own a separate piece without stepping on each other

34* **Debugging with competing hypotheses**: teammates test different theories in parallel and converge on the answer faster

35* **Cross-layer coordination**: changes that span frontend, backend, and tests, each owned by a different teammate

36 

37Agent teams add coordination overhead and use significantly more tokens than a single session. They work best when teammates can operate independently. For sequential tasks, same-file edits, or work with many dependencies, a single session or [subagents](/en/sub-agents) are more effective.

38 

39### Compare with subagents

40 

41Both agent teams and [subagents](/en/sub-agents) let you parallelize work, but they operate differently. Choose based on whether your workers need to communicate with each other:

42 

43<Frame caption="Subagents only report results back to the main agent and never talk to each other. In agent teams, teammates share a task list, claim work, and communicate directly with each other.">

44 <img src="https://mintcdn.com/claude-code/nsvRFSDNfpSU5nT7/images/subagents-vs-agent-teams-light.png?fit=max&auto=format&n=nsvRFSDNfpSU5nT7&q=85&s=2f8db9b4f3705dd3ab931fbe2d96e42a" className="dark:hidden" alt="Diagram comparing subagent and agent team architectures. Subagents are spawned by the main agent, do work, and report results back. Agent teams coordinate through a shared task list, with teammates communicating directly with each other." width="4245" height="1615" data-path="images/subagents-vs-agent-teams-light.png" />

45 

46 <img src="https://mintcdn.com/claude-code/nsvRFSDNfpSU5nT7/images/subagents-vs-agent-teams-dark.png?fit=max&auto=format&n=nsvRFSDNfpSU5nT7&q=85&s=d573a037540f2ada6a9ae7d8285b46fd" className="hidden dark:block" alt="Diagram comparing subagent and agent team architectures. Subagents are spawned by the main agent, do work, and report results back. Agent teams coordinate through a shared task list, with teammates communicating directly with each other." width="4245" height="1615" data-path="images/subagents-vs-agent-teams-dark.png" />

47</Frame>

48 

49| | Subagents | Agent teams |

50| :---------------- | :----------------------------------------------- | :-------------------------------------------------- |

51| **Context** | Own context window; results return to the caller | Own context window; fully independent |

52| **Communication** | Report results back to the main agent only | Teammates message each other directly |

53| **Coordination** | Main agent manages all work | Shared task list with self-coordination |

54| **Best for** | Focused tasks where only the result matters | Complex work requiring discussion and collaboration |

55| **Token cost** | Lower: results summarized back to main context | Higher: each teammate is a separate Claude instance |

56 

57Use subagents when you need quick, focused workers that report back. Use agent teams when teammates need to share findings, challenge each other, and coordinate on their own.

58 

59## Enable agent teams

60 

61Agent teams are disabled by default. Enable them by setting the `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` environment variable to `1`, either in your shell environment or through [settings.json](/en/settings):

62 

63```json settings.json theme={null}

64{

65 "env": {

66 "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"

67 }

68}

69```

70 

71## Start your first agent team

72 

73After enabling agent teams, tell Claude to create an agent team and describe the task and the team structure you want in natural language. Claude creates the team, spawns teammates, and coordinates work based on your prompt.

74 

75This example works well because the three roles are independent and can explore the problem without waiting on each other:

76 

77```text theme={null}

78I'm designing a CLI tool that helps developers track TODO comments across

79their codebase. Create an agent team to explore this from different angles: one

80teammate on UX, one on technical architecture, one playing devil's advocate.

81```

82 

83From there, Claude creates a team with a [shared task list](/en/interactive-mode#task-list), spawns teammates for each perspective, has them explore the problem, synthesizes findings, and attempts to [clean up the team](#clean-up-the-team) when finished.

84 

85The lead's terminal lists all teammates and what they're working on. Use Shift+Down to cycle through teammates and message them directly. After the last teammate, Shift+Down wraps back to the lead.

86 

87If you want each teammate in its own split pane, see [Choose a display mode](#choose-a-display-mode).

88 

89## Control your agent team

90 

91Tell the lead what you want in natural language. It handles team coordination, task assignment, and delegation based on your instructions.

92 

93### Choose a display mode

94 

95Agent teams support two display modes:

96 

97* **In-process**: all teammates run inside your main terminal. Use Shift+Down to cycle through teammates and type to message them directly. Works in any terminal, no extra setup required.

98* **Split panes**: each teammate gets its own pane. You can see everyone's output at once and click into a pane to interact directly. Requires tmux, or iTerm2.

99 

100<Note>

101 `tmux` has known limitations on certain operating systems and traditionally works best on macOS. Using `tmux -CC` in iTerm2 is the suggested entrypoint into `tmux`.

102</Note>

103 

104The default is `"auto"`, which uses split panes if you're already running inside a tmux session, and in-process otherwise. The `"tmux"` setting enables split-pane mode and auto-detects whether to use tmux or iTerm2 based on your terminal. To override, set [`teammateMode`](/en/settings#available-settings) in `~/.claude/settings.json`:

105 

106```json theme={null}

107{

108 "teammateMode": "in-process"

109}

110```

111 

112To force in-process mode for a single session, pass it as a flag:

113 

114```bash theme={null}

115claude --teammate-mode in-process

116```

117 

118Split-pane mode requires either [tmux](https://github.com/tmux/tmux/wiki) or iTerm2 with the [`it2` CLI](https://github.com/mkusaka/it2). To install manually:

119 

120* **tmux**: install through your system's package manager. See the [tmux wiki](https://github.com/tmux/tmux/wiki/Installing) for platform-specific instructions.

121* **iTerm2**: install the [`it2` CLI](https://github.com/mkusaka/it2), then enable the Python API in **iTerm2 → Settings → General → Magic → Enable Python API**.

122 

123### Specify teammates and models

124 

125Claude decides the number of teammates to spawn based on your task, or you can specify exactly what you want:

126 

127```text theme={null}

128Create a team with 4 teammates to refactor these modules in parallel.

129Use Sonnet for each teammate.

130```

131 

132### Require plan approval for teammates

133 

134For complex or risky tasks, you can require teammates to plan before implementing. The teammate works in read-only plan mode until the lead approves their approach:

135 

136```text theme={null}

137Spawn an architect teammate to refactor the authentication module.

138Require plan approval before they make any changes.

139```

140 

141When a teammate finishes planning, it sends a plan approval request to the lead. The lead reviews the plan and either approves it or rejects it with feedback. If rejected, the teammate stays in plan mode, revises based on the feedback, and resubmits. Once approved, the teammate exits plan mode and begins implementation.

142 

143The lead makes approval decisions autonomously. To influence the lead's judgment, give it criteria in your prompt, such as "only approve plans that include test coverage" or "reject plans that modify the database schema."

144 

145### Talk to teammates directly

146 

147Each teammate is a full, independent Claude Code session. You can message any teammate directly to give additional instructions, ask follow-up questions, or redirect their approach.

148 

149* **In-process mode**: use Shift+Down to cycle through teammates, then type to send them a message. Press Enter to view a teammate's session, then Escape to interrupt their current turn. Press Ctrl+T to toggle the task list.

150* **Split-pane mode**: click into a teammate's pane to interact with their session directly. Each teammate has a full view of their own terminal.

151 

152### Assign and claim tasks

153 

154The shared task list coordinates work across the team. The lead creates tasks and teammates work through them. Tasks have three states: pending, in progress, and completed. Tasks can also depend on other tasks: a pending task with unresolved dependencies cannot be claimed until those dependencies are completed.

155 

156The lead can assign tasks explicitly, or teammates can self-claim:

157 

158* **Lead assigns**: tell the lead which task to give to which teammate

159* **Self-claim**: after finishing a task, a teammate picks up the next unassigned, unblocked task on its own

160 

161Task claiming uses file locking to prevent race conditions when multiple teammates try to claim the same task simultaneously.

162 

163### Shut down teammates

164 

165To gracefully end a teammate's session:

166 

167```text theme={null}

168Ask the researcher teammate to shut down

169```

170 

171The lead sends a shutdown request. The teammate can approve, exiting gracefully, or reject with an explanation.

172 

173### Clean up the team

174 

175When you're done, ask the lead to clean up:

176 

177```text theme={null}

178Clean up the team

179```

180 

181This removes the shared team resources. When the lead runs cleanup, it checks for active teammates and fails if any are still running, so shut them down first.

182 

183<Warning>

184 Always use the lead to clean up. Teammates should not run cleanup because their team context may not resolve correctly, potentially leaving resources in an inconsistent state.

185</Warning>

186 

187### Enforce quality gates with hooks

188 

189Use [hooks](/en/hooks) to enforce rules when teammates finish work or tasks are created or completed:

190 

191* [`TeammateIdle`](/en/hooks#teammateidle): runs when a teammate is about to go idle. Exit with code 2 to send feedback and keep the teammate working.

192* [`TaskCreated`](/en/hooks#taskcreated): runs when a task is being created. Exit with code 2 to prevent creation and send feedback.

193* [`TaskCompleted`](/en/hooks#taskcompleted): runs when a task is being marked complete. Exit with code 2 to prevent completion and send feedback.

194 

195## How agent teams work

196 

197This section covers the architecture and mechanics behind agent teams. If you want to start using them, see [Control your agent team](#control-your-agent-team) above.

198 

199### How Claude starts agent teams

200 

201There are two ways agent teams get started:

202 

203* **You request a team**: give Claude a task that benefits from parallel work and explicitly ask for an agent team. Claude creates one based on your instructions.

204* **Claude proposes a team**: if Claude determines your task would benefit from parallel work, it may suggest creating a team. You confirm before it proceeds.

205 

206In both cases, you stay in control. Claude won't create a team without your approval.

207 

208### Architecture

209 

210An agent team consists of:

211 

212| Component | Role |

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

214| **Team lead** | The main Claude Code session that creates the team, spawns teammates, and coordinates work |

215| **Teammates** | Separate Claude Code instances that each work on assigned tasks |

216| **Task list** | Shared list of work items that teammates claim and complete |

217| **Mailbox** | Messaging system for communication between agents |

218 

219See [Choose a display mode](#choose-a-display-mode) for display configuration options. Teammate messages arrive at the lead automatically.

220 

221The system manages task dependencies automatically. When a teammate completes a task that other tasks depend on, blocked tasks unblock without manual intervention.

222 

223Teams and tasks are stored locally:

224 

225* **Team config**: `~/.claude/teams/{team-name}/config.json`

226* **Task list**: `~/.claude/tasks/{team-name}/`

227 

228Claude Code generates both of these automatically when you create a team and updates them as teammates join, go idle, or leave. The team config holds runtime state such as session IDs and tmux pane IDs, so don't edit it by hand or pre-author it: your changes are overwritten on the next state update.

229 

230To define reusable teammate roles, use [subagent definitions](#use-subagent-definitions-for-teammates) instead.

231 

232The team config contains a `members` array with each teammate's name, agent ID, and agent type. Teammates can read this file to discover other team members.

233 

234There is no project-level equivalent of the team config. A file like `.claude/teams/teams.json` in your project directory is not recognized as configuration; Claude treats it as an ordinary file.

235 

236### Use subagent definitions for teammates

237 

238When spawning a teammate, you can reference a [subagent](/en/sub-agents) type from any [subagent scope](/en/sub-agents#choose-the-subagent-scope): project, user, plugin, or CLI-defined. This lets you define a role once, such as a security-reviewer or test-runner, and reuse it both as a delegated subagent and as an agent team teammate.

239 

240To use a subagent definition, mention it by name when asking Claude to spawn the teammate:

241 

242```text theme={null}

243Spawn a teammate using the security-reviewer agent type to audit the auth module.

244```

245 

246The teammate honors that definition's `tools` allowlist and `model`, and the definition's body is appended to the teammate's system prompt as additional instructions rather than replacing it. Team coordination tools such as `SendMessage` and the task management tools are always available to a teammate even when `tools` restricts other tools.

247 

248<Note>

249 The `skills` and `mcpServers` frontmatter fields in a subagent definition are not applied when that definition runs as a teammate. Teammates load skills and MCP servers from your project and user settings, the same as a regular session.

250</Note>

251 

252### Permissions

253 

254Teammates start with the lead's permission settings. If the lead runs with `--dangerously-skip-permissions`, all teammates do too. After spawning, you can change individual teammate modes, but you can't set per-teammate modes at spawn time.

255 

256### Context and communication

257 

258Each teammate has its own context window. When spawned, a teammate loads the same project context as a regular session: CLAUDE.md, MCP servers, and skills. It also receives the spawn prompt from the lead. The lead's conversation history does not carry over.

259 

260**How teammates share information:**

261 

262* **Automatic message delivery**: when teammates send messages, they're delivered automatically to recipients. The lead doesn't need to poll for updates.

263* **Idle notifications**: when a teammate finishes and stops, they automatically notify the lead.

264* **Shared task list**: all agents can see task status and claim available work.

265* **Teammate messaging**: send a message to one specific teammate by name. To reach everyone, send one message per recipient.

266 

267The lead assigns every teammate a name when it spawns them, and any teammate can message any other by that name. To get predictable names you can reference in later prompts, tell the lead what to call each teammate in your spawn instruction.

268 

269### Token usage

270 

271Agent teams use significantly more tokens than a single session. Each teammate has its own context window, and token usage scales with the number of active teammates. For research, review, and new feature work, the extra tokens are usually worthwhile. For routine tasks, a single session is more cost-effective. See [agent team token costs](/en/costs#agent-team-token-costs) for usage guidance.

272 

273## Use case examples

274 

275These examples show how agent teams handle tasks where parallel exploration adds value.

276 

277### Run a parallel code review

278 

279A single reviewer tends to gravitate toward one type of issue at a time. Splitting review criteria into independent domains means security, performance, and test coverage all get thorough attention simultaneously. The prompt assigns each teammate a distinct lens so they don't overlap:

280 

281```text theme={null}

282Create an agent team to review PR #142. Spawn three reviewers:

283- One focused on security implications

284- One checking performance impact

285- One validating test coverage

286Have them each review and report findings.

287```

288 

289Each reviewer works from the same PR but applies a different filter. The lead synthesizes findings across all three after they finish.

290 

291### Investigate with competing hypotheses

292 

293When the root cause is unclear, a single agent tends to find one plausible explanation and stop looking. The prompt fights this by making teammates explicitly adversarial: each one's job is not only to investigate its own theory but to challenge the others'.

294 

295```text theme={null}

296Users report the app exits after one message instead of staying connected.

297Spawn 5 agent teammates to investigate different hypotheses. Have them talk to

298each other to try to disprove each other's theories, like a scientific

299debate. Update the findings doc with whatever consensus emerges.

300```

301 

302The debate structure is the key mechanism here. Sequential investigation suffers from anchoring: once one theory is explored, subsequent investigation is biased toward it.

303 

304With multiple independent investigators actively trying to disprove each other, the theory that survives is much more likely to be the actual root cause.

305 

306## Best practices

307 

308### Give teammates enough context

309 

310Teammates load project context automatically, including CLAUDE.md, MCP servers, and skills, but they don't inherit the lead's conversation history. See [Context and communication](#context-and-communication) for details. Include task-specific details in the spawn prompt:

311 

312```text theme={null}

313Spawn a security reviewer teammate with the prompt: "Review the authentication module

314at src/auth/ for security vulnerabilities. Focus on token handling, session

315management, and input validation. The app uses JWT tokens stored in

316httpOnly cookies. Report any issues with severity ratings."

317```

318 

319### Choose an appropriate team size

320 

321There's no hard limit on the number of teammates, but practical constraints apply:

322 

323* **Token costs scale linearly**: each teammate has its own context window and consumes tokens independently. See [agent team token costs](/en/costs#agent-team-token-costs) for details.

324* **Coordination overhead increases**: more teammates means more communication, task coordination, and potential for conflicts

325* **Diminishing returns**: beyond a certain point, additional teammates don't speed up work proportionally

326 

327Start with 3-5 teammates for most workflows. This balances parallel work with manageable coordination. The examples in this guide use 3-5 teammates because that range works well across different task types.

328 

329Having 5-6 [tasks](/en/agent-teams#architecture) per teammate keeps everyone productive without excessive context switching. If you have 15 independent tasks, 3 teammates is a good starting point.

330 

331Scale up only when the work genuinely benefits from having teammates work simultaneously. Three focused teammates often outperform five scattered ones.

332 

333### Size tasks appropriately

334 

335* **Too small**: coordination overhead exceeds the benefit

336* **Too large**: teammates work too long without check-ins, increasing risk of wasted effort

337* **Just right**: self-contained units that produce a clear deliverable, such as a function, a test file, or a review

338 

339<Tip>

340 The lead breaks work into tasks and assigns them to teammates automatically. If it isn't creating enough tasks, ask it to split the work into smaller pieces. Having 5-6 tasks per teammate keeps everyone productive and lets the lead reassign work if someone gets stuck.

341</Tip>

342 

343### Wait for teammates to finish

344 

345Sometimes the lead starts implementing tasks itself instead of waiting for teammates. If you notice this:

346 

347```text theme={null}

348Wait for your teammates to complete their tasks before proceeding

349```

350 

351### Start with research and review

352 

353If you're new to agent teams, start with tasks that have clear boundaries and don't require writing code: reviewing a PR, researching a library, or investigating a bug. These tasks show the value of parallel exploration without the coordination challenges that come with parallel implementation.

354 

355### Avoid file conflicts

356 

357Two teammates editing the same file leads to overwrites. Break the work so each teammate owns a different set of files.

358 

359### Monitor and steer

360 

361Check in on teammates' progress, redirect approaches that aren't working, and synthesize findings as they come in. Letting a team run unattended for too long increases the risk of wasted effort.

362 

363## Troubleshooting

364 

365### Teammates not appearing

366 

367If teammates aren't appearing after you ask Claude to create a team:

368 

369* In in-process mode, teammates may already be running but not visible. Press Shift+Down to cycle through active teammates.

370* Check that the task you gave Claude was complex enough to warrant a team. Claude decides whether to spawn teammates based on the task.

371* If you explicitly requested split panes, ensure tmux is installed and available in your PATH:

372 ```bash theme={null}

373 which tmux

374 ```

375* For iTerm2, verify the `it2` CLI is installed and the Python API is enabled in iTerm2 preferences.

376 

377### Too many permission prompts

378 

379Teammate permission requests bubble up to the lead, which can create friction. Pre-approve common operations in your [permission settings](/en/permissions) before spawning teammates to reduce interruptions.

380 

381### Teammates stopping on errors

382 

383Teammates may stop after encountering errors instead of recovering. Check their output using Shift+Down in in-process mode or by clicking the pane in split mode, then either:

384 

385* Give them additional instructions directly

386* Spawn a replacement teammate to continue the work

387 

388### Lead shuts down before work is done

389 

390The lead may decide the team is finished before all tasks are actually complete. If this happens, tell it to keep going. You can also tell the lead to wait for teammates to finish before proceeding if it starts doing work instead of delegating.

391 

392### Orphaned tmux sessions

393 

394If a tmux session persists after the team ends, it may not have been fully cleaned up. List sessions and kill the one created by the team:

395 

396```bash theme={null}

397tmux ls

398tmux kill-session -t <session-name>

399```

400 

401## Limitations

402 

403Agent teams are experimental. Current limitations to be aware of:

404 

405* **No session resumption with in-process teammates**: `/resume` and `/rewind` do not restore in-process teammates. After resuming a session, the lead may attempt to message teammates that no longer exist. If this happens, tell the lead to spawn new teammates.

406* **Task status can lag**: teammates sometimes fail to mark tasks as completed, which blocks dependent tasks. If a task appears stuck, check whether the work is actually done and update the task status manually or tell the lead to nudge the teammate.

407* **Shutdown can be slow**: teammates finish their current request or tool call before shutting down, which can take time.

408* **One team per session**: a lead can only manage one team at a time. Clean up the current team before starting a new one.

409* **No nested teams**: teammates cannot spawn their own teams or teammates. Only the lead can manage the team.

410* **Lead is fixed**: the session that creates the team is the lead for its lifetime. You can't promote a teammate to lead or transfer leadership.

411* **Permissions set at spawn**: all teammates start with the lead's permission mode. You can change individual teammate modes after spawning, but you can't set per-teammate modes at spawn time.

412* **Split panes require tmux or iTerm2**: the default in-process mode works in any terminal. Split-pane mode isn't supported in VS Code's integrated terminal, Windows Terminal, or Ghostty.

413 

414<Tip>

415 **`CLAUDE.md` works normally**: teammates read `CLAUDE.md` files from their working directory. Use this to provide project-specific guidance to all teammates.

416</Tip>

417 

418## Next steps

419 

420Explore related approaches for parallel work and delegation:

421 

422* **Lightweight delegation**: [subagents](/en/sub-agents) spawn helper agents for research or verification within your session, better for tasks that don't need inter-agent coordination

423* **Manual parallel sessions**: [Git worktrees](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees) let you run multiple Claude Code sessions yourself without automated team coordination

424* **Compare approaches**: see the [subagent vs agent team](/en/features-overview#compare-similar-features) comparison for a side-by-side breakdown

amazon-bedrock.md +187 −30

Details

6 6 

7> Learn about configuring Claude Code through Amazon Bedrock, including setup, IAM configuration, and troubleshooting.7> Learn about configuring Claude Code through Amazon Bedrock, including setup, IAM configuration, and troubleshooting.

8 8 

9 

10 

11<Experiment flag="docs-contact-sales-cta" treatment={<ContactSalesCard surface="bedrock" />} />

12 

9## Prerequisites13## Prerequisites

10 14 

11Before configuring Claude Code with Bedrock, ensure you have:15Before configuring Claude Code with Bedrock, ensure you have:

12 16 

13* An AWS account with Bedrock access enabled17* An AWS account with Bedrock access enabled

14* Access to desired Claude models (for example, Claude Sonnet 4.5) in Bedrock18* Access to desired Claude models (for example, Claude Sonnet 4.6) in Bedrock

15* AWS CLI installed and configured (optional - only needed if you don't have another mechanism for getting credentials)19* AWS CLI installed and configured (optional - only needed if you don't have another mechanism for getting credentials)

16* Appropriate IAM permissions20* Appropriate IAM permissions

17 21 

18## Setup22To sign in with your own Bedrock credentials, follow [Sign in with Bedrock](#sign-in-with-bedrock) below. To deploy Claude Code across a team, use the [manual setup](#set-up-manually) steps and [pin your model versions](#4-pin-model-versions) before rolling out.

23 

24## Sign in with Bedrock

25 

26If you have AWS credentials and want to start using Claude Code through Bedrock, the login wizard walks you through it. You complete the AWS-side prerequisites once per account; the wizard handles the Claude Code side.

27 

28<Steps>

29 <Step title="Enable Anthropic models in your AWS account">

30 In the [Amazon Bedrock console](https://console.aws.amazon.com/bedrock/), open the Model catalog, select an Anthropic model, and submit the use case form. Access is granted immediately after submission. See [Submit use case details](#1-submit-use-case-details) for AWS Organizations and [IAM configuration](#iam-configuration) for the permissions your role needs.

31 </Step>

32 

33 <Step title="Start Claude Code and choose Bedrock">

34 Run `claude`. At the login prompt, select **3rd-party platform**, then **Amazon Bedrock**.

35 </Step>

36 

37 <Step title="Follow the wizard prompts">

38 Choose how you authenticate to AWS: an AWS profile detected from your `~/.aws` directory, a Bedrock API key, an access key and secret, or credentials already in your environment. The wizard picks up your region, verifies which Claude models your account can invoke, and lets you pin them. It saves the result to the `env` block of your [user settings file](/en/settings), so you don't need to export environment variables yourself.

39 </Step>

40</Steps>

41 

42After you've signed in, run `/setup-bedrock` any time to reopen the wizard and change your credentials, region, or model pins.

43 

44## Set up manually

45 

46To configure Bedrock through environment variables instead of the wizard, for example in CI or a scripted enterprise rollout, follow the steps below.

19 47 

20### 1. Submit use case details48### 1. Submit use case details

21 49 

22First-time users of Anthropic models are required to submit use case details before invoking a model. This is done once per account.50First-time users of Anthropic models are required to submit use case details before invoking a model. This is done once per AWS account.

23 51 

241. Ensure you have the right IAM permissions (see more on that below)521. Ensure you have the right IAM permissions described below

252. Navigate to the [Amazon Bedrock console](https://console.aws.amazon.com/bedrock/)532. Navigate to the [Amazon Bedrock console](https://console.aws.amazon.com/bedrock/)

263. Select **Chat/Text playground**543. Select an Anthropic model from the **Model catalog**

274. Choose any Anthropic model and you will be prompted to fill out the use case form554. Complete the use case form. Access is granted immediately after submission.

56 

57If you use AWS Organizations, you can submit the form once from the management account using the [`PutUseCaseForModelAccess` API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_PutUseCaseForModelAccess.html). This call requires the `bedrock:PutUseCaseForModelAccess` IAM permission. Approval extends to child accounts automatically.

28 58 

29### 2. Configure AWS credentials59### 2. Configure AWS credentials

30 60 


110export CLAUDE_CODE_USE_BEDROCK=1140export CLAUDE_CODE_USE_BEDROCK=1

111export AWS_REGION=us-east-1 # or your preferred region141export AWS_REGION=us-east-1 # or your preferred region

112 142 

113# Optional: Override the region for the small/fast model (Haiku)143# Optional: Override the region for the small/fast model (Haiku).

144# Also applies to Bedrock Mantle.

114export ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION=us-west-2145export ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION=us-west-2

146 

147# Optional: Override the Bedrock endpoint URL for custom endpoints or gateways

148# export ANTHROPIC_BEDROCK_BASE_URL=https://bedrock-runtime.us-east-1.amazonaws.com

115```149```

116 150 

117When enabling Bedrock for Claude Code, keep the following in mind:151When enabling Bedrock for Claude Code, keep the following in mind:


120* When using Bedrock, the `/login` and `/logout` commands are disabled since authentication is handled through AWS credentials.154* When using Bedrock, the `/login` and `/logout` commands are disabled since authentication is handled through AWS credentials.

121* You can use settings files for environment variables like `AWS_PROFILE` that you don't want to leak to other processes. See [Settings](/en/settings) for more information.155* You can use settings files for environment variables like `AWS_PROFILE` that you don't want to leak to other processes. See [Settings](/en/settings) for more information.

122 156 

123### 4. Model configuration157### 4. Pin model versions

158 

159<Warning>

160 Pin specific model versions when deploying to multiple users. Without pinning, model aliases such as `sonnet` and `opus` resolve to the latest version, which may not yet be available in your Bedrock account when Anthropic releases an update. Claude Code [falls back](#startup-model-checks) to the previous version at startup when the latest is unavailable, but pinning lets you control when your users move to a new model.

161</Warning>

162 

163Set these environment variables to specific Bedrock model IDs.

164 

165Without `ANTHROPIC_DEFAULT_OPUS_MODEL`, the `opus` alias on Bedrock resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:

124 166 

125Claude Code uses these default models for Bedrock:167```bash theme={null}

168export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-7'

169export ANTHROPIC_DEFAULT_SONNET_MODEL='us.anthropic.claude-sonnet-4-6'

170export ANTHROPIC_DEFAULT_HAIKU_MODEL='us.anthropic.claude-haiku-4-5-20251001-v1:0'

171```

172 

173These variables use cross-region inference profile IDs (with the `us.` prefix). If you use a different region prefix or application inference profiles, adjust accordingly. For current and legacy model IDs, see [Models overview](https://platform.claude.com/docs/en/about-claude/models/overview). See [Model configuration](/en/model-config#pin-models-for-third-party-deployments) for the full list of environment variables.

174 

175Claude Code uses these default models when no pinning variables are set:

126 176 

127| Model type | Default value |177| Model type | Default value |

128| :--------------- | :------------------------------------------------- |178| :--------------- | :--------------------------------------------- |

129| Primary model | `global.anthropic.claude-sonnet-4-5-20250929-v1:0` |179| Primary model | `us.anthropic.claude-sonnet-4-5-20250929-v1:0` |

130| Small/fast model | `us.anthropic.claude-haiku-4-5-20251001-v1:0` |180| Small/fast model | `us.anthropic.claude-haiku-4-5-20251001-v1:0` |

131 181 

132<Note>182To customize models further, use one of these methods:

133 For Bedrock users, Claude Code won't automatically upgrade from Haiku 3.5 to Haiku 4.5. To manually switch to a newer Haiku model, set the `ANTHROPIC_DEFAULT_HAIKU_MODEL` environment variable to the full model name (for example, `us.anthropic.claude-haiku-4-5-20251001-v1:0`).

134</Note>

135 

136To customize models, use one of these methods:

137 183 

138```bash theme={null}184```bash theme={null}

139# Using inference profile ID185# Using inference profile ID

140export ANTHROPIC_MODEL='global.anthropic.claude-sonnet-4-5-20250929-v1:0'186export ANTHROPIC_MODEL='global.anthropic.claude-sonnet-4-6'

141export ANTHROPIC_SMALL_FAST_MODEL='us.anthropic.claude-haiku-4-5-20251001-v1:0'187export ANTHROPIC_DEFAULT_HAIKU_MODEL='us.anthropic.claude-haiku-4-5-20251001-v1:0'

142 188 

143# Using application inference profile ARN189# Using application inference profile ARN

144export ANTHROPIC_MODEL='arn:aws:bedrock:us-east-2:your-account-id:application-inference-profile/your-model-id'190export ANTHROPIC_MODEL='arn:aws:bedrock:us-east-2:your-account-id:application-inference-profile/your-model-id'

145 191 

146# Optional: Disable prompt caching if needed192# Optional: Disable prompt caching if needed

147export DISABLE_PROMPT_CACHING=1193export DISABLE_PROMPT_CACHING=1

194 

195# Optional: Request 1-hour prompt cache TTL instead of the 5-minute default

196export ENABLE_PROMPT_CACHING_1H=1

148```197```

149 198 

150<Note>[Prompt caching](https://docs.claude.com/en/docs/build-with-claude/prompt-caching) may not be available in all regions.</Note>199<Note>[Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) may not be available in all regions. Cache writes with a 1-hour TTL are billed at a higher rate than 5-minute writes.</Note>

151 200 

152### 5. Output token configuration201#### Map each model version to an inference profile

153 202 

154These are the recommended token settings for Claude Code with Amazon Bedrock:203The `ANTHROPIC_DEFAULT_*_MODEL` environment variables configure one inference profile per model family. If your organization needs to expose several versions of the same family in the `/model` picker, each routed to its own application inference profile ARN, use the `modelOverrides` setting in your [settings file](/en/settings#settings-files) instead.

155 204 

156```bash theme={null}205This example maps four Opus versions to distinct ARNs so users can switch between them without bypassing your organization's inference profiles:

157# Recommended output token settings for Bedrock206 

158export CLAUDE_CODE_MAX_OUTPUT_TOKENS=4096207```json theme={null}

159export MAX_THINKING_TOKENS=1024208{

209 "modelOverrides": {

210 "claude-opus-4-7": "arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-47-prod",

211 "claude-opus-4-6": "arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-46-prod",

212 "claude-opus-4-5-20251101": "arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-45-prod",

213 "claude-opus-4-1-20250805": "arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-41-prod"

214 }

215}

160```216```

161 217 

162**Why these values:**218When a user selects one of these versions in `/model`, Claude Code calls Bedrock with the mapped ARN. Versions without an override fall back to the built-in Bedrock model ID or any matching inference profile discovered at startup. See [Override model IDs per version](/en/model-config#override-model-ids-per-version) for details on how overrides interact with `availableModels` and other model settings.

219 

220## Startup model checks

221 

222When Claude Code starts with Bedrock configured, it verifies that the models it intends to use are accessible in your account. This check requires Claude Code v2.1.94 or later.

163 223 

164* **`CLAUDE_CODE_MAX_OUTPUT_TOKENS=4096`**: Bedrock's burndown throttling logic sets a minimum of 4096 tokens as the `max_token` penalty. Setting this lower won't reduce costs but may cut off long tool uses, causing the Claude Code agent loop to fail persistently. Claude Code typically uses less than 4096 output tokens without extended thinking, but may need this headroom for tasks involving significant file creation or Write tool usage.224If you have pinned a model version that is older than the current Claude Code default, and your account can invoke the newer version, Claude Code prompts you to update the pin. Accepting writes the new model ID to your [user settings file](/en/settings) and restarts Claude Code. Declining is remembered until the next default version change. Pins that point to an [application inference profile ARN](#map-each-model-version-to-an-inference-profile) are skipped, since those are managed by your administrator.

165 225 

166* **`MAX_THINKING_TOKENS=1024`**: This provides space for extended thinking without cutting off tool use responses, while still maintaining focused reasoning chains. This balance helps prevent trajectory changes that aren't always helpful for coding tasks specifically.226If you have not pinned a model and the current default is unavailable in your account, Claude Code falls back to the previous version for the current session and shows a notice. The fallback is not persisted. Enable the newer model in your Bedrock account or [pin a version](#4-pin-model-versions) to make the choice permanent.

167 227 

168## IAM configuration228## IAM configuration

169 229 


210For details, see [Bedrock IAM documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html).270For details, see [Bedrock IAM documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html).

211 271 

212<Note>272<Note>

213 We recommend creating a dedicated AWS account for Claude Code to simplify cost tracking and access control.273 Create a dedicated AWS account for Claude Code to simplify cost tracking and access control.

214</Note>274</Note>

215 275 

276## 1M token context window

277 

278Claude Opus 4.7, Opus 4.6, and Sonnet 4.6 support the [1M token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#1m-token-context-window) on Amazon Bedrock. Claude Code automatically enables the extended context window when you select a 1M model variant.

279 

280The [setup wizard](#sign-in-with-bedrock) offers a 1M context option when it pins models. To enable it for a manually pinned model instead, append `[1m]` to the model ID. See [Pin models for third-party deployments](/en/model-config#pin-models-for-third-party-deployments) for details.

281 

216## AWS Guardrails282## AWS Guardrails

217 283 

218[Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) let you implement content filtering for Claude Code. Create a Guardrail in the [Amazon Bedrock console](https://console.aws.amazon.com/bedrock/), publish a version, then add the Guardrail headers to your [settings file](/en/settings). Enable Cross-Region inference on your Guardrail if you're using cross-region inference profiles.284[Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) let you implement content filtering for Claude Code. Create a Guardrail in the [Amazon Bedrock console](https://console.aws.amazon.com/bedrock/), publish a version, then add the Guardrail headers to your [settings file](/en/settings). Enable Cross-Region inference on your Guardrail if you're using cross-region inference profiles.


227}293}

228```294```

229 295 

296## Use the Mantle endpoint

297 

298Mantle is an Amazon Bedrock endpoint that serves Claude models through the native Anthropic API shape rather than the Bedrock Invoke API. It uses the same AWS credentials, IAM permissions, and `awsAuthRefresh` configuration described earlier on this page.

299 

300<Note>

301 Mantle requires Claude Code v2.1.94 or later. Run `claude --version` to check.

302</Note>

303 

304### Enable Mantle

305 

306With AWS credentials already configured, set `CLAUDE_CODE_USE_MANTLE` to route requests to the Mantle endpoint:

307 

308```bash theme={null}

309export CLAUDE_CODE_USE_MANTLE=1

310export AWS_REGION=us-east-1

311```

312 

313Claude Code constructs the endpoint URL from `AWS_REGION`. To override it for a custom endpoint or gateway, set `ANTHROPIC_BEDROCK_MANTLE_BASE_URL`.

314 

315Run `/status` inside Claude Code to confirm. The provider line shows `Amazon Bedrock (Mantle)` when Mantle is active.

316 

317### Select a Mantle model

318 

319Mantle uses model IDs prefixed with `anthropic.` and without a version suffix, for example `anthropic.claude-haiku-4-5`. The models available to your account depend on what your organization has been granted; additional model IDs are listed in your onboarding materials from AWS. Contact your AWS account team to request access to allowlisted models.

320 

321Set the model with the `--model` flag or with `/model` inside Claude Code:

322 

323```bash theme={null}

324claude --model anthropic.claude-haiku-4-5

325```

326 

327### Run Mantle alongside the Invoke API

328 

329The models available to you on Mantle may not include every model you use today. Setting both `CLAUDE_CODE_USE_BEDROCK` and `CLAUDE_CODE_USE_MANTLE` lets Claude Code call both endpoints from the same session. Model IDs that match the Mantle format are routed to Mantle, and all other model IDs go to the Bedrock Invoke API.

330 

331```bash theme={null}

332export CLAUDE_CODE_USE_BEDROCK=1

333export CLAUDE_CODE_USE_MANTLE=1

334```

335 

336To surface a Mantle model in the `/model` picker, list its ID in `availableModels` in your [settings file](/en/settings). This setting also restricts the picker to the listed entries, so include every alias you want to keep available:

337 

338```json theme={null}

339{

340 "availableModels": ["opus", "sonnet", "haiku", "anthropic.claude-haiku-4-5"]

341}

342```

343 

344Entries with the `anthropic.` prefix are added as custom picker options and routed to Mantle. Replace `anthropic.claude-haiku-4-5` with the model ID your account has been granted. See [Restrict model selection](/en/model-config#restrict-model-selection) for how `availableModels` interacts with other model settings.

345 

346When both providers are active, `/status` shows `Amazon Bedrock + Amazon Bedrock (Mantle)`.

347 

348### Route Mantle through a gateway

349 

350If your organization routes model traffic through a centralized [LLM gateway](/en/llm-gateway) that injects AWS credentials server-side, disable client-side authentication so Claude Code sends requests without SigV4 signatures or `x-api-key` headers:

351 

352```bash theme={null}

353export CLAUDE_CODE_USE_MANTLE=1

354export CLAUDE_CODE_SKIP_MANTLE_AUTH=1

355export ANTHROPIC_BEDROCK_MANTLE_BASE_URL=https://your-gateway.example.com

356```

357 

358### Mantle environment variables

359 

360These variables are specific to the Mantle endpoint. See [Environment variables](/en/env-vars) for the full list.

361 

362| Variable | Purpose |

363| :-------------------------------------- | :------------------------------------------------------------------ |

364| `CLAUDE_CODE_USE_MANTLE` | Enable the Mantle endpoint. Set to `1` or `true`. |

365| `ANTHROPIC_BEDROCK_MANTLE_BASE_URL` | Override the default Mantle endpoint URL |

366| `CLAUDE_CODE_SKIP_MANTLE_AUTH` | Skip client-side authentication for proxy setups |

367| `ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION` | Override AWS region for the Haiku-class model (shared with Bedrock) |

368 

230## Troubleshooting369## Troubleshooting

231 370 

371### Authentication loop with SSO and corporate proxies

372 

373If browser tabs spawn repeatedly when using AWS SSO, remove the `awsAuthRefresh` setting from your [settings file](/en/settings). This can occur when corporate VPNs or TLS inspection proxies interrupt the SSO browser flow. Claude Code treats the interrupted connection as an authentication failure, re-runs `awsAuthRefresh`, and loops indefinitely.

374 

375If your network environment interferes with automatic browser-based SSO flows, use `aws sso login` manually before starting Claude Code instead of relying on `awsAuthRefresh`.

376 

377### Region issues

378 

232If you encounter region issues:379If you encounter region issues:

233 380 

234* Check model availability: `aws bedrock list-inference-profiles --region your-region`381* Check model availability: `aws bedrock list-inference-profiles --region your-region`


241 388 

242Claude Code uses the Bedrock [Invoke API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html) and does not support the Converse API.389Claude Code uses the Bedrock [Invoke API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html) and does not support the Converse API.

243 390 

391### Mantle endpoint errors

392 

393If `/status` does not show `Amazon Bedrock (Mantle)` after you set `CLAUDE_CODE_USE_MANTLE`, the variable is not reaching the process. Confirm it is exported in the shell where you launched `claude`, or set it in the `env` block of your [settings file](/en/settings).

394 

395A `403` from the Mantle endpoint with valid credentials means your AWS account has not been granted access to the model you requested. Contact your AWS account team to request access.

396 

397A `400` that names the model ID means that model is not served on Mantle. Mantle has its own model lineup separate from the standard Bedrock catalog, so inference profile IDs such as `us.anthropic.claude-sonnet-4-6` will not work. Use a Mantle-format ID, or enable [both endpoints](#run-mantle-alongside-the-invoke-api) so Claude Code routes each request to the endpoint where the model is available.

398 

244## Additional resources399## Additional resources

245 400 

246* [Bedrock documentation](https://docs.aws.amazon.com/bedrock/)401* [Bedrock documentation](https://docs.aws.amazon.com/bedrock/)

247* [Bedrock pricing](https://aws.amazon.com/bedrock/pricing/)402* [Bedrock pricing](https://aws.amazon.com/bedrock/pricing/)

248* [Bedrock inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html)403* [Bedrock inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html)

249* [Claude Code on Amazon Bedrock: Quick Setup Guide](https://community.aws/content/2tXkZKrZzlrlu0KfH8gST5Dkppq/claude-code-on-amazon-bedrock-quick-setup-guide)- [Claude Code Monitoring Implementation (Bedrock)](https://github.com/aws-solutions-library-samples/guidance-for-claude-code-with-amazon-bedrock/blob/main/assets/docs/MONITORING.md)404* [Bedrock token burndown and quotas](https://docs.aws.amazon.com/bedrock/latest/userguide/quotas-token-burndown.html)

405* [Claude Code on Amazon Bedrock: Quick Setup Guide](https://community.aws/content/2tXkZKrZzlrlu0KfH8gST5Dkppq/claude-code-on-amazon-bedrock-quick-setup-guide)

406* [Claude Code Monitoring Implementation (Bedrock)](https://github.com/aws-solutions-library-samples/guidance-for-claude-code-with-amazon-bedrock/blob/main/assets/docs/MONITORING.md)

analytics.md +9 −5

Details

9Claude Code provides analytics dashboards to help organizations understand developer usage patterns, track contribution metrics, and measure how Claude Code impacts engineering velocity. Access the dashboard for your plan:9Claude Code provides analytics dashboards to help organizations understand developer usage patterns, track contribution metrics, and measure how Claude Code impacts engineering velocity. Access the dashboard for your plan:

10 10 

11| Plan | Dashboard URL | Includes | Read more |11| Plan | Dashboard URL | Includes | Read more |

12| ----------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------- |12| ----------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------- |

13| Claude for Teams / Enterprise | [claude.ai/analytics/claude-code](https://claude.ai/analytics/claude-code) | Usage metrics, contribution metrics with GitHub integration, leaderboard, data export | [Details](#access-analytics-for-teams-and-enterprise) |13| Claude for Teams / Enterprise | [claude.ai/analytics/claude-code](https://claude.ai/analytics/claude-code) | Usage metrics, contribution metrics with GitHub integration, leaderboard, data export | [Details](#access-analytics-for-team-and-enterprise) |

14| API (Claude Console) | [platform.claude.com/claude-code](https://platform.claude.com/claude-code) | Usage metrics, spend tracking, team insights | [Details](#access-analytics-for-api-customers) |14| API (Claude Console) | [platform.claude.com/claude-code](https://platform.claude.com/claude-code) | Usage metrics, spend tracking, team insights | [Details](#access-analytics-for-api-customers) |

15 15 

16## Access analytics for Teams and Enterprise16## Access analytics for Team and Enterprise

17 17 

18Navigate to [claude.ai/analytics/claude-code](https://claude.ai/analytics/claude-code). Admins and Owners can view the dashboard.18Navigate to [claude.ai/analytics/claude-code](https://claude.ai/analytics/claude-code). Admins and Owners can view the dashboard.

19 19 

20The Teams and Enterprise dashboard includes:20The Team and Enterprise dashboard includes:

21 21 

22* **Usage metrics**: lines of code accepted, suggestion accept rate, daily active users and sessions22* **Usage metrics**: lines of code accepted, suggestion accept rate, daily active users and sessions

23* **Contribution metrics**: PRs and lines of code shipped with Claude Code assistance, with [GitHub integration](#enable-contribution-metrics)23* **Contribution metrics**: PRs and lines of code shipped with Claude Code assistance, with [GitHub integration](#enable-contribution-metrics)


34 34 

35You need the Owner role to configure analytics settings. A GitHub admin must install the GitHub app.35You need the Owner role to configure analytics settings. A GitHub admin must install the GitHub app.

36 36 

37<Warning>

38 Contribution metrics are not available for organizations with [Zero Data Retention](/en/zero-data-retention) enabled. The analytics dashboard will show usage metrics only.

39</Warning>

40 

37<Steps>41<Steps>

38 <Step title="Install the GitHub app">42 <Step title="Install the GitHub app">

39 A GitHub admin installs the Claude GitHub app on your organization's GitHub account at [github.com/apps/claude](https://github.com/apps/claude).43 A GitHub admin installs the Claude GitHub app on your organization's GitHub account at [github.com/apps/claude](https://github.com/apps/claude).


217 221 

218* [Monitoring with OpenTelemetry](/en/monitoring-usage): export real-time metrics and events to your observability stack222* [Monitoring with OpenTelemetry](/en/monitoring-usage): export real-time metrics and events to your observability stack

219* [Manage costs effectively](/en/costs): set spend limits and optimize token usage223* [Manage costs effectively](/en/costs): set spend limits and optimize token usage

220* [Identity and access management](/en/iam): configure roles and permissions224* [Permissions](/en/permissions): configure roles and permissions

authentication.md +155 −0 added

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# Authentication

6 

7> Log in to Claude Code and configure authentication for individuals, teams, and organizations.

8 

9Claude Code supports multiple authentication methods depending on your setup. Individual users can log in with a Claude.ai account, while teams can use Claude for Teams or Enterprise, the Claude Console, or a cloud provider like Amazon Bedrock, Google Vertex AI, or Microsoft Foundry.

10 

11## Log in to Claude Code

12 

13After [installing Claude Code](/en/setup#install-claude-code), run `claude` in your terminal. On first launch, Claude Code opens a browser window for you to log in.

14 

15If the browser doesn't open automatically, press `c` to copy the login URL to your clipboard, then paste it into your browser.

16 

17If your browser shows a login code instead of redirecting back after you sign in, paste it into the terminal at the `Paste code here if prompted` prompt.

18 

19You can authenticate with any of these account types:

20 

21* **Claude Pro or Max subscription**: log in with your Claude.ai account. Subscribe at [claude.com/pricing](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=authentication_pro_max).

22* **Claude for Teams or Enterprise**: log in with the Claude.ai account your team admin invited you to.

23* **Claude Console**: log in with your Console credentials. Your admin must have [invited you](#claude-console-authentication) first.

24* **Cloud providers**: if your organization uses [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), or [Microsoft Foundry](/en/microsoft-foundry), set the required environment variables before running `claude`. No browser login is needed.

25 

26To log out and re-authenticate, type `/logout` at the Claude Code prompt.

27 

28If you're having trouble logging in, see [authentication troubleshooting](/en/troubleshooting#authentication-issues).

29 

30## Set up team authentication

31 

32For teams and organizations, you can configure Claude Code access in one of these ways:

33 

34* [Claude for Teams or Enterprise](#claude-for-teams-or-enterprise), recommended for most teams

35* [Claude Console](#claude-console-authentication)

36* [Amazon Bedrock](/en/amazon-bedrock)

37* [Google Vertex AI](/en/google-vertex-ai)

38* [Microsoft Foundry](/en/microsoft-foundry)

39 

40### Claude for Teams or Enterprise

41 

42[Claude for Teams](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=authentication_teams#team-&-enterprise) and [Claude for Enterprise](https://anthropic.com/contact-sales?utm_source=claude_code\&utm_medium=docs\&utm_content=authentication_enterprise) provide the best experience for organizations using Claude Code. Team members get access to both Claude Code and Claude on the web with centralized billing and team management.

43 

44* **Claude for Teams**: self-service plan with collaboration features, admin tools, and billing management. Best for smaller teams.

45* **Claude for Enterprise**: adds SSO, domain capture, role-based permissions, compliance API, and managed policy settings for organization-wide Claude Code configurations. Best for larger organizations with security and compliance requirements.

46 

47<Steps>

48 <Step title="Subscribe">

49 Subscribe to [Claude for Teams](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=authentication_teams_step#team-&-enterprise) or contact sales for [Claude for Enterprise](https://anthropic.com/contact-sales?utm_source=claude_code\&utm_medium=docs\&utm_content=authentication_enterprise_step).

50 </Step>

51 

52 <Step title="Invite team members">

53 Invite team members from the admin dashboard.

54 </Step>

55 

56 <Step title="Install and log in">

57 Team members install Claude Code and log in with their Claude.ai accounts.

58 </Step>

59</Steps>

60 

61### Claude Console authentication

62 

63For organizations that prefer API-based billing, you can set up access through the Claude Console.

64 

65<Steps>

66 <Step title="Create or use a Console account">

67 Use your existing Claude Console account or create a new one.

68 </Step>

69 

70 <Step title="Add users">

71 You can add users through either method:

72 

73 * Bulk invite users from within the Console: Settings -> Members -> Invite

74 * [Set up SSO](https://support.claude.com/en/articles/13132885-setting-up-single-sign-on-sso)

75 </Step>

76 

77 <Step title="Assign roles">

78 When inviting users, assign one of:

79 

80 * **Claude Code** role: users can only create Claude Code API keys

81 * **Developer** role: users can create any kind of API key

82 </Step>

83 

84 <Step title="Users complete setup">

85 Each invited user needs to:

86 

87 * Accept the Console invite

88 * [Check system requirements](/en/setup#system-requirements)

89 * [Install Claude Code](/en/setup#install-claude-code)

90 * Log in with Console account credentials

91 </Step>

92</Steps>

93 

94### Cloud provider authentication

95 

96For teams using Amazon Bedrock, Google Vertex AI, or Microsoft Foundry:

97 

98<Steps>

99 <Step title="Follow provider setup">

100 Follow the [Bedrock docs](/en/amazon-bedrock), [Vertex docs](/en/google-vertex-ai), or [Microsoft Foundry docs](/en/microsoft-foundry).

101 </Step>

102 

103 <Step title="Distribute configuration">

104 Distribute the environment variables and instructions for generating cloud credentials to your users. Read more about how to [manage configuration here](/en/settings).

105 </Step>

106 

107 <Step title="Install Claude Code">

108 Users can [install Claude Code](/en/setup#install-claude-code).

109 </Step>

110</Steps>

111 

112## Credential management

113 

114Claude Code securely manages your authentication credentials:

115 

116* **Storage location**: on macOS, credentials are stored in the encrypted macOS Keychain. On Linux and Windows, credentials are stored in `~/.claude/.credentials.json`, or under `$CLAUDE_CONFIG_DIR` if that variable is set. On Linux, the file is written with mode `0600`; on Windows, it inherits the access controls of your user profile directory.

117* **Supported authentication types**: Claude.ai credentials, Claude API credentials, Azure Auth, Bedrock Auth, and Vertex Auth.

118* **Custom credential scripts**: the [`apiKeyHelper`](/en/settings#available-settings) setting can be configured to run a shell script that returns an API key.

119* **Refresh intervals**: by default, `apiKeyHelper` is called after 5 minutes or on HTTP 401 response. Set `CLAUDE_CODE_API_KEY_HELPER_TTL_MS` environment variable for custom refresh intervals.

120* **Slow helper notice**: if `apiKeyHelper` takes longer than 10 seconds to return a key, Claude Code displays a warning notice in the prompt bar showing the elapsed time. If you see this notice regularly, check whether your credential script can be optimized.

121 

122`apiKeyHelper`, `ANTHROPIC_API_KEY`, and `ANTHROPIC_AUTH_TOKEN` apply to terminal CLI sessions only. Claude Desktop and remote sessions use OAuth exclusively and do not call `apiKeyHelper` or read API key environment variables.

123 

124### Authentication precedence

125 

126When multiple credentials are present, Claude Code chooses one in this order:

127 

1281. Cloud provider credentials, when `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, or `CLAUDE_CODE_USE_FOUNDRY` is set. See [third-party integrations](/en/third-party-integrations) for setup.

1292. `ANTHROPIC_AUTH_TOKEN` environment variable. Sent as the `Authorization: Bearer` header. Use this when routing through an [LLM gateway or proxy](/en/llm-gateway) that authenticates with bearer tokens rather than Anthropic API keys.

1303. `ANTHROPIC_API_KEY` environment variable. Sent as the `X-Api-Key` header. Use this for direct Anthropic API access with a key from the [Claude Console](https://platform.claude.com). In interactive mode, you are prompted once to approve or decline the key, and your choice is remembered. To change it later, use the "Use custom API key" toggle in `/config`. In non-interactive mode (`-p`), the key is always used when present.

1314. [`apiKeyHelper`](/en/settings#available-settings) script output. Use this for dynamic or rotating credentials, such as short-lived tokens fetched from a vault.

1325. `CLAUDE_CODE_OAUTH_TOKEN` environment variable. A long-lived OAuth token generated by [`claude setup-token`](#generate-a-long-lived-token). Use this for CI pipelines and scripts where browser login isn't available.

1336. Subscription OAuth credentials from `/login`. This is the default for Claude Pro, Max, Team, and Enterprise users.

134 

135If you have an active Claude subscription but also have `ANTHROPIC_API_KEY` set in your environment, the API key takes precedence once approved. This can cause authentication failures if the key belongs to a disabled or expired organization. Run `unset ANTHROPIC_API_KEY` to fall back to your subscription, and check `/status` to confirm which method is active.

136 

137[Claude Code on the Web](/en/claude-code-on-the-web) always uses your subscription credentials. `ANTHROPIC_API_KEY` and `ANTHROPIC_AUTH_TOKEN` in the sandbox environment do not override them.

138 

139### Generate a long-lived token

140 

141For CI pipelines, scripts, or other environments where interactive browser login isn't available, generate a one-year OAuth token with `claude setup-token`:

142 

143```bash theme={null}

144claude setup-token

145```

146 

147The command walks you through OAuth authorization and prints a token to the terminal. It does not save the token anywhere; copy it and set it as the `CLAUDE_CODE_OAUTH_TOKEN` environment variable wherever you want to authenticate:

148 

149```bash theme={null}

150export CLAUDE_CODE_OAUTH_TOKEN=your-token

151```

152 

153This token authenticates with your Claude subscription and requires a Pro, Max, Team, or Enterprise plan. It is scoped to inference only and cannot establish [Remote Control](/en/remote-control) sessions.

154 

155[Bare mode](/en/headless#start-faster-with-bare-mode) does not read `CLAUDE_CODE_OAUTH_TOKEN`. If your script passes `--bare`, authenticate with `ANTHROPIC_API_KEY` or an `apiKeyHelper` instead.

auto-mode-config.md +174 −0 added

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# Configure auto mode

6 

7> Tell the auto mode classifier which repos, buckets, and domains your organization trusts. Set environment context, override the default block and allow rules, and inspect your effective config with the auto-mode CLI subcommands.

8 

9[Auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) lets Claude Code run without permission prompts by routing each tool call through a classifier that blocks anything irreversible, destructive, or aimed outside your environment. Use the `autoMode` settings block to tell that classifier which repos, buckets, and domains your organization trusts, so it stops blocking routine internal operations.

10 

11Out of the box, the classifier trusts only the working directory and the current repo's configured remotes. Actions like pushing to your company's source-control org or writing to a team cloud bucket are blocked until you add them to `autoMode.environment`.

12 

13For how to enable auto mode and what it blocks by default, see [Permission modes](/en/permission-modes#eliminate-prompts-with-auto-mode). This page is the configuration reference.

14 

15This page covers how to:

16 

17* [Choose where to set rules](#where-the-classifier-reads-configuration) across CLAUDE.md, user settings, and managed settings

18* [Define trusted infrastructure](#define-trusted-infrastructure) with `autoMode.environment`

19* [Override the block and allow rules](#override-the-block-and-allow-rules) when the defaults don't fit your pipeline

20* [Inspect your effective config](#inspect-the-defaults-and-your-effective-config) with the `claude auto-mode` subcommands

21* [Review denials](#review-denials) so you know what to add next

22 

23## Where the classifier reads configuration

24 

25The classifier reads the same [CLAUDE.md](/en/memory) content Claude itself loads, so an instruction like "never force push" in your project's CLAUDE.md steers both Claude and the classifier at the same time. Start there for project conventions and behavioral rules.

26 

27For rules that apply across projects, such as trusted infrastructure or organization-wide deny rules, use the `autoMode` settings block. The classifier reads `autoMode` from the following scopes:

28 

29| Scope | File | Use for |

30| :----------------------------- | :---------------------------------------------- | :--------------------------------------------------- |

31| One developer | `~/.claude/settings.json` | Personal trusted infrastructure |

32| One project, one developer | `.claude/settings.local.json` | Per-project trusted buckets or services, gitignored |

33| Organization-wide | [Managed settings](/en/server-managed-settings) | Trusted infrastructure distributed to all developers |

34| `--settings` flag or Agent SDK | Inline JSON | Per-invocation overrides for automation |

35 

36The classifier does not read `autoMode` from shared project settings in `.claude/settings.json`, so a checked-in repo cannot inject its own allow rules.

37 

38Entries from each scope are combined. A developer can extend `environment`, `allow`, and `soft_deny` with personal entries but cannot remove entries that managed settings provide. Because allow rules act as exceptions to block rules inside the classifier, a developer-added `allow` entry can override an organization `soft_deny` entry: the combination is additive, not a hard policy boundary.

39 

40<Note>

41 The classifier is a second gate that runs after the [permissions system](/en/permissions). For actions that must never run regardless of user intent or classifier configuration, use `permissions.deny` in managed settings, which blocks the action before the classifier is consulted and cannot be overridden.

42</Note>

43 

44## Define trusted infrastructure

45 

46For most organizations, `autoMode.environment` is the only field you need to set. It tells the classifier which repos, buckets, and domains are trusted: the classifier uses it to decide what "external" means, so any destination not listed is a potential exfiltration target.

47 

48The default environment list trusts the working repo and its configured remotes. To add your own entries alongside that default, include the literal string `"$defaults"` in the array. The default entries are spliced in at that position, so your custom entries can go before or after them.

49 

50```json theme={null}

51{

52 "autoMode": {

53 "environment": [

54 "$defaults",

55 "Source control: github.example.com/acme-corp and all repos under it",

56 "Trusted cloud buckets: s3://acme-build-artifacts, gs://acme-ml-datasets",

57 "Trusted internal domains: *.corp.example.com, api.internal.example.com",

58 "Key internal services: Jenkins at ci.example.com, Artifactory at artifacts.example.com"

59 ]

60 }

61}

62```

63 

64Entries are prose, not regex or tool patterns. The classifier reads them as natural-language rules. Write them the way you would describe your infrastructure to a new engineer. A thorough environment section covers:

65 

66* **Organization**: your company name and what Claude Code is primarily used for, like software development, infrastructure automation, or data engineering

67* **Source control**: every GitHub, GitLab, or Bitbucket org your developers push to

68* **Cloud providers and trusted buckets**: bucket names or prefixes that Claude should be able to read from and write to

69* **Trusted internal domains**: hostnames for APIs, dashboards, and services inside your network, like `*.internal.example.com`

70* **Key internal services**: CI, artifact registries, internal package indexes, incident tooling

71* **Additional context**: regulated-industry constraints, multi-tenant infrastructure, or compliance requirements that affect what the classifier should treat as risky

72 

73A useful starting template: fill in the bracketed fields and remove any lines that don't apply.

74 

75```json theme={null}

76{

77 "autoMode": {

78 "environment": [

79 "$defaults",

80 "Organization: {COMPANY_NAME}. Primary use: {PRIMARY_USE_CASE, e.g. software development, infrastructure automation}",

81 "Source control: {SOURCE_CONTROL, e.g. GitHub org github.example.com/acme-corp}",

82 "Cloud provider(s): {CLOUD_PROVIDERS, e.g. AWS, GCP, Azure}",

83 "Trusted cloud buckets: {TRUSTED_BUCKETS, e.g. s3://acme-builds, gs://acme-datasets}",

84 "Trusted internal domains: {TRUSTED_DOMAINS, e.g. *.internal.example.com, api.example.com}",

85 "Key internal services: {SERVICES, e.g. Jenkins at ci.example.com, Artifactory at artifacts.example.com}",

86 "Additional context: {EXTRA, e.g. regulated industry, multi-tenant infrastructure, compliance requirements}"

87 ]

88 }

89}

90```

91 

92The more specific context you give, the better the classifier can distinguish routine internal operations from exfiltration attempts.

93 

94You don't need to fill everything in at once. A reasonable rollout: start with the defaults and add your source control org and key internal services, which resolves the most common false positives like pushing to your own repos. Add trusted domains and cloud buckets next. Fill the rest as blocks come up.

95 

96## Override the block and allow rules

97 

98Two additional fields let you replace the classifier's built-in rule lists: `autoMode.soft_deny` controls what gets blocked, and `autoMode.allow` controls which exceptions apply. Each is an array of prose descriptions, read as natural-language rules. There is no `autoMode.deny` field; to hard-block an action regardless of intent, use [`permissions.deny`](/en/permissions), which runs before the classifier.

99 

100Inside the classifier, precedence works in three tiers:

101 

102* `soft_deny` rules block first

103* `allow` rules then override matching blocks as exceptions

104* Explicit user intent overrides both: if the user's message directly and specifically describes the exact action Claude is about to take, the classifier allows it even when a `soft_deny` rule matches

105 

106General requests don't count as explicit intent. Asking Claude to "clean up the repo" does not authorize force-pushing, but asking Claude to "force-push this branch" does.

107 

108To loosen, add to `allow` when the classifier repeatedly flags a routine pattern the default exceptions don't cover. To tighten, add to `soft_deny` for risks specific to your environment that the defaults miss. To keep the built-in rules while adding your own, include the literal string `"$defaults"` in the array. The default rules are spliced in at that position, so your custom rules can go before or after them, and you continue to inherit updates as the built-in list changes across releases.

109 

110```json theme={null}

111{

112 "autoMode": {

113 "environment": [

114 "$defaults",

115 "Source control: github.example.com/acme-corp and all repos under it"

116 ],

117 "allow": [

118 "$defaults",

119 "Deploying to the staging namespace is allowed: staging is isolated from production and resets nightly",

120 "Writing to s3://acme-scratch/ is allowed: ephemeral bucket with a 7-day lifecycle policy"

121 ],

122 "soft_deny": [

123 "$defaults",

124 "Never run database migrations outside the migrations CLI, even against dev databases",

125 "Never modify files under infra/terraform/prod/: production infrastructure changes go through the review workflow"

126 ]

127 }

128}

129```

130 

131<Danger>

132 Setting any of `environment`, `allow`, or `soft_deny` without `"$defaults"` replaces the entire default list for that section. If you set `soft_deny` with a single entry and omit `"$defaults"`, every built-in block rule is discarded: force push, data exfiltration, `curl | bash`, production deploys, and all other default block rules become allowed. Only omit `"$defaults"` when you intend to take full ownership of the list. In that case, run `claude auto-mode defaults` to print the built-in rules, copy them into your settings file, then review each rule against your own pipeline and risk tolerance.

133</Danger>

134 

135Each section is evaluated independently, so setting `environment` alone leaves the default `allow` and `soft_deny` lists intact.

136 

137## Inspect the defaults and your effective config

138 

139Three CLI subcommands help you inspect and validate your configuration.

140 

141Print the built-in `environment`, `allow`, and `soft_deny` rules as JSON:

142 

143```bash theme={null}

144claude auto-mode defaults

145```

146 

147Print what the classifier actually uses as JSON, with your settings applied where set and defaults otherwise:

148 

149```bash theme={null}

150claude auto-mode config

151```

152 

153Get AI feedback on your custom `allow` and `soft_deny` rules:

154 

155```bash theme={null}

156claude auto-mode critique

157```

158 

159Run `claude auto-mode config` after saving your settings to confirm the effective rules are what you expect, with `"$defaults"` expanded in place. If you've written custom rules, `claude auto-mode critique` reviews them and flags entries that are ambiguous, redundant, or likely to cause false positives. If you need to remove or rewrite a built-in rule rather than add alongside it, save the output of `claude auto-mode defaults` to a file, edit the lists, and paste the result into your settings file in place of `"$defaults"`.

160 

161## Review denials

162 

163When auto mode denies a tool call, the denial is recorded in `/permissions` under the Recently denied tab. Press `r` on a denied action to mark it for retry: when you exit the dialog, Claude Code sends a message telling the model it may retry that tool call and resumes the conversation.

164 

165Repeated denials for the same destination usually mean the classifier is missing context. Add that destination to `autoMode.environment`, then run `claude auto-mode config` to confirm it took effect.

166 

167To react to denials programmatically, use the [`PermissionDenied` hook](/en/hooks#permissiondenied).

168 

169## See also

170 

171* [Permission modes](/en/permission-modes#eliminate-prompts-with-auto-mode): what auto mode is, what it blocks by default, and how to enable it

172* [Managed settings](/en/server-managed-settings): deploy `autoMode` configuration across your organization

173* [Permissions](/en/permissions): allow, ask, and deny rules that apply before the classifier runs

174* [Settings](/en/settings): the full settings reference, including the `autoMode` key

best-practices.md +42 −56

Details

20 20 

21Claude's context window holds your entire conversation, including every message, every file Claude reads, and every command output. However, this can fill up fast. A single debugging session or codebase exploration might generate and consume tens of thousands of tokens.21Claude's context window holds your entire conversation, including every message, every file Claude reads, and every command output. However, this can fill up fast. A single debugging session or codebase exploration might generate and consume tens of thousands of tokens.

22 22 

23This matters since LLM performance degrades as context fills. When the context window is getting full, Claude may start "forgetting" earlier instructions or making more mistakes. The context window is the most important resource to manage. For detailed strategies on reducing token usage, see [Reduce token usage](/en/costs#reduce-token-usage).23This matters since LLM performance degrades as context fills. When the context window is getting full, Claude may start "forgetting" earlier instructions or making more mistakes. The context window is the most important resource to manage. To see how a session fills up in practice, [watch an interactive walkthrough](/en/context-window) of what loads at startup and what each file read costs. Track context usage continuously with a [custom status line](/en/statusline), and see [Reduce token usage](/en/costs#reduce-token-usage) for strategies on reducing token usage.

24 24 

25***25***

26 26 


40| **Verify UI changes visually** | *"make the dashboard look better"* | *"\[paste screenshot] implement this design. take a screenshot of the result and compare it to the original. list differences and fix them"* |40| **Verify UI changes visually** | *"make the dashboard look better"* | *"\[paste screenshot] implement this design. take a screenshot of the result and compare it to the original. list differences and fix them"* |

41| **Address root causes, not symptoms** | *"the build is failing"* | *"the build fails with this error: \[paste error]. fix it and verify the build succeeds. address the root cause, don't suppress the error"* |41| **Address root causes, not symptoms** | *"the build is failing"* | *"the build fails with this error: \[paste error]. fix it and verify the build succeeds. address the root cause, don't suppress the error"* |

42 42 

43UI changes can be verified using the [Claude in Chrome extension](/en/chrome). It opens a browser, tests the UI, and iterates until the code works.43UI changes can be verified using the [Claude in Chrome extension](/en/chrome). It opens new tabs in your browser, tests the UI, and iterates until the code works.

44 44 

45Your verification can also be a test suite, a linter, or a Bash command that checks output. Invest in making your verification rock-solid.45Your verification can also be a test suite, a linter, or a Bash command that checks output. Invest in making your verification rock-solid.

46 46 


148 Run `/init` to generate a starter CLAUDE.md file based on your current project structure, then refine over time.148 Run `/init` to generate a starter CLAUDE.md file based on your current project structure, then refine over time.

149</Tip>149</Tip>

150 150 

151CLAUDE.md is a special file that Claude reads at the start of every conversation. Include Bash commands, code style, and workflow rules. This gives Claude persistent context **it can't infer from code alone**.151CLAUDE.md is a special file that Claude reads at the start of every conversation. Include Bash commands, code style, and workflow rules. This gives Claude persistent context it can't infer from code alone.

152 152 

153The `/init` command analyzes your codebase to detect build systems, test frameworks, and code patterns, giving you a solid foundation to refine.153The `/init` command analyzes your codebase to detect build systems, test frameworks, and code patterns, giving you a solid foundation to refine.

154 154 


194 194 

195You can place CLAUDE.md files in several locations:195You can place CLAUDE.md files in several locations:

196 196 

197* **Home folder (`~/.claude/CLAUDE.md`)**: Applies to all Claude sessions197* **Home folder (`~/.claude/CLAUDE.md`)**: applies to all Claude sessions

198* **Project root (`./CLAUDE.md`)**: Check into git to share with your team, or name it `CLAUDE.local.md` and `.gitignore` it198* **Project root (`./CLAUDE.md`)**: check into git to share with your team

199* **Parent directories**: Useful for monorepos where both `root/CLAUDE.md` and `root/foo/CLAUDE.md` are pulled in automatically199* **Project root (`./CLAUDE.local.md`)**: personal project-specific notes; add this file to your `.gitignore` so it isn't shared with your team

200* **Parent directories**: useful for monorepos where both `root/CLAUDE.md` and `root/foo/CLAUDE.md` are pulled in automatically

200* **Child directories**: Claude pulls in child CLAUDE.md files on demand when working with files in those directories201* **Child directories**: Claude pulls in child CLAUDE.md files on demand when working with files in those directories

201 202 

202### Configure permissions203### Configure permissions

203 204 

204<Tip>205<Tip>

205 Use `/permissions` to allowlist safe commands or `/sandbox` for OS-level isolation. This reduces interruptions while keeping you in control.206 Use [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) to let a classifier handle approvals, `/permissions` to allowlist specific commands, or `/sandbox` for OS-level isolation. Each reduces interruptions while keeping you in control.

206</Tip>207</Tip>

207 208 

208By default, Claude Code requests permission for actions that might modify your system: file writes, Bash commands, MCP tools, etc. This is safe but tedious. After the tenth approval you're not really reviewing anymore, you're just clicking through. There are two ways to reduce these interruptions:209By default, Claude Code requests permission for actions that might modify your system: file writes, Bash commands, MCP tools, etc. This is safe but tedious. After the tenth approval you're not really reviewing anymore, you're just clicking through. There are three ways to reduce these interruptions:

209 210 

210* **Permission allowlists**: Permit specific tools you know are safe (like `npm run lint` or `git commit`)211* **Auto mode**: a separate classifier model reviews commands and blocks only what looks risky: scope escalation, unknown infrastructure, or hostile-content-driven actions. Best when you trust the general direction of a task but don't want to click through every step

211* **Sandboxing**: Enable OS-level isolation that restricts filesystem and network access, allowing Claude to work more freely within defined boundaries212* **Permission allowlists**: permit specific tools you know are safe, like `npm run lint` or `git commit`

213* **Sandboxing**: enable OS-level isolation that restricts filesystem and network access, allowing Claude to work more freely within defined boundaries

212 214 

213Alternatively, use `--dangerously-skip-permissions` to bypass all permission checks for contained workflows like fixing lint errors or generating boilerplate.215Read more about [permission modes](/en/permission-modes), [permission rules](/en/permissions), and [sandboxing](/en/sandboxing).

214 

215<Warning>

216 Letting Claude run arbitrary commands can result in data loss, system corruption, or data exfiltration via prompt injection. Only use `--dangerously-skip-permissions` in a sandbox without internet access.

217</Warning>

218 

219Read more about [configuring permissions](/en/settings) and [enabling sandboxing](/en/sandboxing#sandboxing).

220 216 

221### Use CLI tools217### Use CLI tools

222 218 


244 240 

245[Hooks](/en/hooks-guide) run scripts automatically at specific points in Claude's workflow. Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens.241[Hooks](/en/hooks-guide) run scripts automatically at specific points in Claude's workflow. Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens.

246 242 

247Claude can write hooks for you. Try prompts like *"Write a hook that runs eslint after every file edit"* or *"Write a hook that blocks writes to the migrations folder."* Run `/hooks` for interactive configuration, or edit `.claude/settings.json` directly.243Claude can write hooks for you. Try prompts like *"Write a hook that runs eslint after every file edit"* or *"Write a hook that blocks writes to the migrations folder."* Edit `.claude/settings.json` directly to configure hooks by hand, and run `/hooks` to browse what's configured.

248 244 

249### Create skills245### Create skills

250 246 


356 352 

357Claude asks about things you might not have considered yet, including technical implementation, UI/UX, edge cases, and tradeoffs.353Claude asks about things you might not have considered yet, including technical implementation, UI/UX, edge cases, and tradeoffs.

358 354 

359```355```text theme={null}

360I want to build [brief description]. Interview me in detail using the AskUserQuestion tool.356I want to build [brief description]. Interview me in detail using the AskUserQuestion tool.

361 357 

362Ask about technical implementation, UI/UX, edge cases, concerns, and tradeoffs. Don't ask obvious questions, dig into the hard parts I might not have considered.358Ask about technical implementation, UI/UX, edge cases, concerns, and tradeoffs. Don't ask obvious questions, dig into the hard parts I might not have considered.


380 376 

381The best results come from tight feedback loops. Though Claude occasionally solves problems perfectly on the first attempt, correcting it quickly generally produces better solutions faster.377The best results come from tight feedback loops. Though Claude occasionally solves problems perfectly on the first attempt, correcting it quickly generally produces better solutions faster.

382 378 

383* **`Esc`**: Stop Claude mid-action with the `Esc` key. Context is preserved, so you can redirect.379* **`Esc`**: stop Claude mid-action with the `Esc` key. Context is preserved, so you can redirect.

384* **`Esc + Esc` or `/rewind`**: Press `Esc` twice or run `/rewind` to open the rewind menu and restore previous conversation and code state.380* **`Esc + Esc` or `/rewind`**: press `Esc` twice or run `/rewind` to open the rewind menu and restore previous conversation and code state, or summarize from a selected message.

385* **`"Undo that"`**: Have Claude revert its changes.381* **`"Undo that"`**: have Claude revert its changes.

386* **`/clear`**: Reset context between unrelated tasks. Long sessions with irrelevant context can reduce performance.382* **`/clear`**: reset context between unrelated tasks. Long sessions with irrelevant context can reduce performance.

387 383 

388If you've corrected Claude more than twice on the same issue in one session, the context is cluttered with failed approaches. Run `/clear` and start fresh with a more specific prompt that incorporates what you learned. A clean session with a better prompt almost always outperforms a long session with accumulated corrections.384If you've corrected Claude more than twice on the same issue in one session, the context is cluttered with failed approaches. Run `/clear` and start fresh with a more specific prompt that incorporates what you learned. A clean session with a better prompt almost always outperforms a long session with accumulated corrections.

389 385 


400* Use `/clear` frequently between tasks to reset the context window entirely396* Use `/clear` frequently between tasks to reset the context window entirely

401* When auto compaction triggers, Claude summarizes what matters most, including code patterns, file states, and key decisions397* When auto compaction triggers, Claude summarizes what matters most, including code patterns, file states, and key decisions

402* For more control, run `/compact <instructions>`, like `/compact Focus on the API changes`398* For more control, run `/compact <instructions>`, like `/compact Focus on the API changes`

399* To compact only part of the conversation, use `Esc + Esc` or `/rewind`, select a message checkpoint, and choose **Summarize from here**. This condenses messages from that point forward while keeping earlier context intact.

403* Customize compaction behavior in CLAUDE.md with instructions like `"When compacting, always preserve the full list of modified files and any test commands"` to ensure critical context survives summarization400* Customize compaction behavior in CLAUDE.md with instructions like `"When compacting, always preserve the full list of modified files and any test commands"` to ensure critical context survives summarization

401* For quick questions that don't need to stay in context, use [`/btw`](/en/interactive-mode#side-questions-with-%2Fbtw). The answer appears in a dismissible overlay and never enters conversation history, so you can check a detail without growing context.

404 402 

405### Use subagents for investigation403### Use subagents for investigation

406 404 


410 408 

411Since context is your fundamental constraint, subagents are one of the most powerful tools available. When Claude researches a codebase it reads lots of files, all of which consume your context. Subagents run in separate context windows and report back summaries:409Since context is your fundamental constraint, subagents are one of the most powerful tools available. When Claude researches a codebase it reads lots of files, all of which consume your context. Subagents run in separate context windows and report back summaries:

412 410 

413```411```text theme={null}

414Use subagents to investigate how our authentication system handles token412Use subagents to investigate how our authentication system handles token

415refresh, and whether we have any existing OAuth utilities I should reuse.413refresh, and whether we have any existing OAuth utilities I should reuse.

416```414```


419 417 

420You can also use subagents for verification after Claude implements something:418You can also use subagents for verification after Claude implements something:

421 419 

422```420```text theme={null}

423use a subagent to review this code for edge cases421use a subagent to review this code for edge cases

424```422```

425 423 


429 Every action Claude makes creates a checkpoint. You can restore conversation, code, or both to any previous checkpoint.427 Every action Claude makes creates a checkpoint. You can restore conversation, code, or both to any previous checkpoint.

430</Tip>428</Tip>

431 429 

432Claude automatically checkpoints before changes. Double-tap `Escape` or run `/rewind` to open the checkpoint menu. You can restore conversation only (keep code changes), restore code only (keep conversation), or restore both.430Claude automatically checkpoints before changes. Double-tap `Escape` or run `/rewind` to open the rewind menu. You can restore conversation only, restore code only, restore both, or summarize from a selected message. See [Checkpointing](/en/checkpointing) for details.

433 431 

434Instead of carefully planning every move, you can tell Claude to try something risky. If it doesn't work, rewind and try a different approach. Checkpoints persist across sessions, so you can close your terminal and still rewind later.432Instead of carefully planning every move, you can tell Claude to try something risky. If it doesn't work, rewind and try a different approach. Checkpoints persist across sessions, so you can close your terminal and still rewind later.

435 433 


443 Run `claude --continue` to pick up where you left off, or `--resume` to choose from recent sessions.441 Run `claude --continue` to pick up where you left off, or `--resume` to choose from recent sessions.

444</Tip>442</Tip>

445 443 

446Claude Code saves conversations locally. When a task spans multiple sessions (you start a feature, get interrupted, come back the next day) you don't have to re-explain the context:444Claude Code saves conversations locally. When a task spans multiple sessions, you don't have to re-explain the context:

447 445 

448```bash theme={null}446```bash theme={null}

449claude --continue # Resume the most recent conversation447claude --continue # Resume the most recent conversation

450claude --resume # Select from recent conversations448claude --resume # Select from recent conversations

451```449```

452 450 

453Use `/rename` to give sessions descriptive names (`"oauth-migration"`, `"debugging-memory-leak"`) so you can find them later. Treat sessions like branches. Different workstreams can have separate, persistent contexts.451Use `/rename` to give sessions descriptive names like `"oauth-migration"` or `"debugging-memory-leak"` so you can find them later. Treat sessions like branches: different workstreams can have separate, persistent contexts.

454 452 

455***453***

456 454 

457## Automate and scale455## Automate and scale

458 456 

459Once you're effective with one Claude, multiply your output with parallel sessions, headless mode, and fan-out patterns.457Once you're effective with one Claude, multiply your output with parallel sessions, non-interactive mode, and fan-out patterns.

460 458 

461Everything so far assumes one human, one Claude, and one conversation. But Claude Code scales horizontally. The techniques in this section show how you can get more done.459Everything so far assumes one human, one Claude, and one conversation. But Claude Code scales horizontally. The techniques in this section show how you can get more done.

462 460 

463### Run headless mode461### Run non-interactive mode

464 462 

465<Tip>463<Tip>

466 Use `claude -p "prompt"` in CI, pre-commit hooks, or scripts. Add `--output-format stream-json` for streaming JSON output.464 Use `claude -p "prompt"` in CI, pre-commit hooks, or scripts. Add `--output-format stream-json` for streaming JSON output.

467</Tip>465</Tip>

468 466 

469With `claude -p "your prompt"`, you can run Claude headlessly, without an interactive session. Headless mode is how you integrate Claude into CI pipelines, pre-commit hooks, or any automated workflow. The output formats (plain text, JSON, streaming JSON) let you parse results programmatically.467With `claude -p "your prompt"`, you can run Claude non-interactively, without a session. Non-interactive mode is how you integrate Claude into CI pipelines, pre-commit hooks, or any automated workflow. The output formats let you parse results programmatically: plain text, JSON, or streaming JSON.

470 468 

471```bash theme={null}469```bash theme={null}

472# One-off queries470# One-off queries


485 Run multiple Claude sessions in parallel to speed up development, run isolated experiments, or start complex workflows.483 Run multiple Claude sessions in parallel to speed up development, run isolated experiments, or start complex workflows.

486</Tip>484</Tip>

487 485 

488There are two main ways to run parallel sessions:486There are three main ways to run parallel sessions:

489 487 

490* [Claude Desktop](/en/desktop): Manage multiple local sessions visually. Each session gets its own isolated worktree.488* [Claude Code desktop app](/en/desktop#work-in-parallel-with-sessions): Manage multiple local sessions visually. Each session gets its own isolated worktree.

491* [Claude Code on the web](/en/claude-code-on-the-web): Run on Anthropic's secure cloud infrastructure in isolated VMs.489* [Claude Code on the web](/en/claude-code-on-the-web): Run on Anthropic's secure cloud infrastructure in isolated VMs.

490* [Agent teams](/en/agent-teams): Automated coordination of multiple sessions with shared tasks, messaging, and a team lead.

492 491 

493Beyond parallelizing work, multiple sessions enable quality-focused workflows. A fresh context improves code review since Claude won't be biased toward code it just wrote.492Beyond parallelizing work, multiple sessions enable quality-focused workflows. A fresh context improves code review since Claude won't be biased toward code it just wrote.

494 493 


537 536 

538Use `--verbose` for debugging during development, and turn it off in production.537Use `--verbose` for debugging during development, and turn it off in production.

539 538 

540### Safe Autonomous Mode539### Run autonomously with auto mode

541 540 

542Use `claude --dangerously-skip-permissions` to bypass all permission checks and let Claude work uninterrupted. This works well for workflows like fixing lint errors or generating boilerplate code.541For uninterrupted execution with background safety checks, use [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode). A classifier model reviews commands before they run, blocking scope escalation, unknown infrastructure, and hostile-content-driven actions while letting routine work proceed without prompts.

543 542 

544<Warning>543```bash theme={null}

545 Letting Claude run arbitrary commands is risky and can result in data loss, system corruption, or data exfiltration (e.g., via prompt injection attacks). To minimize these risks, use `--dangerously-skip-permissions` in a container without internet access.544claude --permission-mode auto -p "fix all lint errors"

545```

546 546 

547 With sandboxing enabled (`/sandbox`), you get similar autonomy with better security. Sandbox defines upfront boundaries rather than bypassing all checks.547For non-interactive runs with the `-p` flag, auto mode aborts if the classifier repeatedly blocks actions, since there is no user to fall back to. See [when auto mode falls back](/en/permission-modes#when-auto-mode-falls-back) for thresholds.

548</Warning>

549 548 

550***549***

551 550 


578 577 

579## Related resources578## Related resources

580 579 

581<CardGroup cols={2}>580* [How Claude Code works](/en/how-claude-code-works): the agentic loop, tools, and context management

582 <Card title="How Claude Code works" icon="gear" href="/en/how-claude-code-works">581* [Extend Claude Code](/en/features-overview): skills, hooks, MCP, subagents, and plugins

583 Understand the agentic loop, tools, and context management582* [Common workflows](/en/common-workflows): step-by-step recipes for debugging, testing, PRs, and more

584 </Card>583* [CLAUDE.md](/en/memory): store project conventions and persistent context

585 

586 <Card title="Extend Claude Code" icon="puzzle-piece" href="/en/features-overview">

587 Choose between skills, hooks, MCP, subagents, and plugins

588 </Card>

589 

590 <Card title="Common workflows" icon="list-check" href="/en/common-workflows">

591 Step-by-step recipes for debugging, testing, PRs, and more

592 </Card>

593 

594 <Card title="CLAUDE.md" icon="file-lines" href="/en/memory">

595 Store project conventions and persistent context

596 </Card>

597</CardGroup>

channels.md +357 −0 added

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 

15Unlike integrations that spawn a fresh cloud session or wait to be polled, the event arrives in the session you already have open: see [how channels compare](#how-channels-compare).

16 

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

18 

19When 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.

20 

21This page covers:

22 

23* [Supported channels](#supported-channels): Telegram, Discord, and iMessage setup

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

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

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

27* [How channels compare](#how-channels-compare) to web sessions, Slack, MCP, and Remote Control

28 

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

30 

31## Supported channels

32 

33Each 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).

34 

35<Tabs>

36 <Tab title="Telegram">

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

38 

39 <Steps>

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

41 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.

42 </Step>

43 

44 <Step title="Install the plugin">

45 In Claude Code, run:

46 

47 ```

48 /plugin install telegram@claude-plugins-official

49 ```

50 

51 If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run `/plugin marketplace update claude-plugins-official` to refresh it, or `/plugin marketplace add anthropics/claude-plugins-official` if you haven't added it before. Then retry the install.

52 

53 After installing, run `/reload-plugins` to activate the plugin's configure command.

54 </Step>

55 

56 <Step title="Configure your token">

57 Run the configure command with the token from BotFather:

58 

59 ```

60 /telegram:configure <token>

61 ```

62 

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

64 </Step>

65 

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

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

68 

69 ```bash theme={null}

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

71 ```

72 </Step>

73 

74 <Step title="Pair your account">

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

76 

77 <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>

78 

79 Back in Claude Code, run:

80 

81 ```

82 /telegram:access pair <code>

83 ```

84 

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

86 

87 ```

88 /telegram:access policy allowlist

89 ```

90 </Step>

91 </Steps>

92 </Tab>

93 

94 <Tab title="Discord">

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

96 

97 <Steps>

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

99 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.

100 </Step>

101 

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

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

104 </Step>

105 

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

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

108 

109 * View Channels

110 * Send Messages

111 * Send Messages in Threads

112 * Read Message History

113 * Attach Files

114 * Add Reactions

115 

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

117 </Step>

118 

119 <Step title="Install the plugin">

120 In Claude Code, run:

121 

122 ```

123 /plugin install discord@claude-plugins-official

124 ```

125 

126 If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run `/plugin marketplace update claude-plugins-official` to refresh it, or `/plugin marketplace add anthropics/claude-plugins-official` if you haven't added it before. Then retry the install.

127 

128 After installing, run `/reload-plugins` to activate the plugin's configure command.

129 </Step>

130 

131 <Step title="Configure your token">

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

133 

134 ```

135 /discord:configure <token>

136 ```

137 

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

139 </Step>

140 

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

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

143 

144 ```bash theme={null}

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

146 ```

147 </Step>

148 

149 <Step title="Pair your account">

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

151 

152 <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>

153 

154 Back in Claude Code, run:

155 

156 ```

157 /discord:access pair <code>

158 ```

159 

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

161 

162 ```

163 /discord:access policy allowlist

164 ```

165 </Step>

166 </Steps>

167 </Tab>

168 

169 <Tab title="iMessage">

170 View the full [iMessage plugin source](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/imessage).

171 

172 The iMessage channel reads your Messages database directly and sends replies through AppleScript. It requires macOS and needs no bot token or external service.

173 

174 <Steps>

175 <Step title="Grant Full Disk Access">

176 The Messages database at `~/Library/Messages/chat.db` is protected by macOS. The first time the server reads it, macOS prompts for access: click **Allow**. The prompt names whichever app launched Bun, such as Terminal, iTerm, or your IDE.

177 

178 If the prompt doesn't appear or you clicked Don't Allow, grant access manually under **System Settings > Privacy & Security > Full Disk Access** and add your terminal. Without this, the server exits immediately with `authorization denied`.

179 </Step>

180 

181 <Step title="Install the plugin">

182 In Claude Code, run:

183 

184 ```

185 /plugin install imessage@claude-plugins-official

186 ```

187 

188 If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run `/plugin marketplace update claude-plugins-official` to refresh it, or `/plugin marketplace add anthropics/claude-plugins-official` if you haven't added it before. Then retry the install.

189 </Step>

190 

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

192 Exit Claude Code and restart with the channel flag:

193 

194 ```bash theme={null}

195 claude --channels plugin:imessage@claude-plugins-official

196 ```

197 </Step>

198 

199 <Step title="Text yourself">

200 Open Messages on any device signed into your Apple ID and send a message to yourself. It reaches Claude immediately: self-chat bypasses access control with no setup.

201 

202 <Note>The first reply Claude sends triggers a macOS Automation prompt asking if your terminal can control Messages. Click **OK**.</Note>

203 </Step>

204 

205 <Step title="Allow other senders">

206 By default, only your own messages pass through. To let another contact reach Claude, add their handle:

207 

208 ```

209 /imessage:access allow +15551234567

210 ```

211 

212 Handles are phone numbers in `+country` format or Apple ID emails like `user@example.com`.

213 </Step>

214 </Steps>

215 </Tab>

216</Tabs>

217 

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

219 

220## Quickstart

221 

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

223 

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

225 

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

227 

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

229* [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).

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

231 

232<Steps>

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

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

235 

236 ```text theme={null}

237 /plugin install fakechat@claude-plugins-official

238 ```

239 

240 If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run `/plugin marketplace update claude-plugins-official` to refresh it, or `/plugin marketplace add anthropics/claude-plugins-official` if you haven't added it before. Then retry the install.

241 </Step>

242 

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

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

245 

246 ```bash theme={null}

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

248 ```

249 

250 The fakechat server starts automatically.

251 

252 <Tip>

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

254 </Tip>

255 </Step>

256 

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

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

259 

260 ```text theme={null}

261 hey, what's in my working directory?

262 ```

263 

264 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.

265 </Step>

266</Steps>

267 

268If Claude hits a permission prompt while you're away from the terminal, the session pauses until you respond. Channel servers that declare the [permission relay capability](/en/channels-reference#relay-permission-prompts) can forward these prompts to you so you can approve or deny remotely. For unattended use, [`--dangerously-skip-permissions`](/en/permission-modes#skip-all-checks-with-bypasspermissions-mode) bypasses prompts entirely, but only use it in environments you trust.

269 

270## Security

271 

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

273 

274Telegram and Discord bootstrap the list by pairing:

275 

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

2772. The bot replies with a pairing code

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

2794. Your sender ID is added to the allowlist

280 

281iMessage works differently: texting yourself bypasses the gate automatically, and you add other contacts by handle with `/imessage:access allow`.

282 

283On 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).

284 

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

286 

287The allowlist also gates [permission relay](/en/channels-reference#relay-permission-prompts) if the channel declares it. Anyone who can reply through the channel can approve or deny tool use in your session, so only allowlist senders you trust with that authority.

288 

289## Enterprise controls

290 

291On Team and Enterprise plans, channels are off by default. Admins control availability through two [managed settings](/en/settings) that users cannot override:

292 

293| Setting | Purpose | When not configured |

294| :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------- |

295| `channelsEnabled` | Master switch. Must be `true` for any channel to deliver messages. Set via the [claude.ai Admin console](https://claude.ai/admin-settings/claude-code) toggle or directly in managed settings. Blocks all channels including the development flag when off. | Channels blocked |

296| `allowedChannelPlugins` | Which plugins can register once channels are enabled. Replaces the Anthropic-maintained list when set. Only applies when `channelsEnabled` is `true`. | Anthropic default list applies |

297 

298Pro and Max users without an organization skip these checks entirely: channels are available and users opt in per session with `--channels`.

299 

300### Enable channels for your organization

301 

302Admins 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.

303 

304Once 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.

305 

306### Restrict which channel plugins can run

307 

308By default, any plugin on the Anthropic-maintained allowlist can register as a channel. Admins on Team and Enterprise plans can replace that allowlist with their own by setting `allowedChannelPlugins` in managed settings. Use this to restrict which official plugins are allowed, approve channels from your own internal marketplace, or both. Each entry names a plugin and the marketplace it comes from:

309 

310```json theme={null}

311{

312 "channelsEnabled": true,

313 "allowedChannelPlugins": [

314 { "marketplace": "claude-plugins-official", "plugin": "telegram" },

315 { "marketplace": "claude-plugins-official", "plugin": "discord" },

316 { "marketplace": "acme-corp-plugins", "plugin": "internal-alerts" }

317 ]

318}

319```

320 

321When `allowedChannelPlugins` is set, it replaces the Anthropic allowlist entirely: only the listed plugins can register. Leave it unset to fall back to the default Anthropic allowlist. An empty array blocks all channel plugins from the allowlist, but `--dangerously-load-development-channels` can still bypass it for local testing. To block channels entirely including the development flag, leave `channelsEnabled` unset instead.

322 

323This setting requires `channelsEnabled: true`. If a user passes a plugin to `--channels` that isn't on your list, Claude Code starts normally but the channel doesn't register, and the startup notice explains that the plugin isn't on the organization's approved list.

324 

325## Research preview

326 

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

328 

329During the preview, `--channels` only accepts plugins from an Anthropic-maintained allowlist, or from your organization's allowlist if an admin has set [`allowedChannelPlugins`](#restrict-which-channel-plugins-can-run). The channel plugins in [claude-plugins-official](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins) are the default approved set. If you pass something that isn't on the effective allowlist, Claude Code starts normally but the channel doesn't register, and the startup notice tells you why.

330 

331To 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.

332 

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

334 

335## How channels compare

336 

337Several Claude Code features connect to systems outside the terminal, each suited to a different kind of work:

338 

339| Feature | What it does | Good for |

340| ---------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------- |

341| [Claude Code on the web](/en/claude-code-on-the-web) | Runs tasks in a fresh cloud sandbox, cloned from GitHub | Delegating self-contained async work you check on later |

342| [Claude in Slack](/en/slack) | Spawns a web session from an `@Claude` mention in a channel or thread | Starting tasks directly from team conversation context |

343| Standard [MCP server](/en/mcp) | Claude queries it during a task; nothing is pushed to the session | Giving Claude on-demand access to read or query a system |

344| [Remote Control](/en/remote-control) | You drive your local session from claude.ai or the Claude mobile app | Steering an in-progress session while away from your desk |

345 

346Channels fill the gap in that list by pushing events from non-Claude sources into your already-running local session.

347 

348* **Chat bridge**: ask Claude something from your phone via Telegram, Discord, or iMessage, and the answer comes back in the same chat while the work runs on your machine against your real files.

349* **[Webhook receiver](/en/channels-reference#example-build-a-webhook-receiver)**: a webhook from CI, your error tracker, a deploy pipeline, or other external service arrives where Claude already has your files open and remembers what you were debugging.

350 

351## Next steps

352 

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

354 

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

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

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

channels-reference.md +749 −0 added

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, sender gating, and permission relay.

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. A channel with a trusted sender path can also opt in to [relay permission prompts](#relay-permission-prompts) so you can approve or deny tool use remotely.

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* [Relay permission prompts](#relay-permission-prompts): forward tool approval prompts to remote channels

27 

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

29 

30## Overview

31 

32A 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:

33 

34* **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.

35* **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.

36 

37<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" />

38 

39## What you need

40 

41The 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.

42 

43Your server needs to:

44 

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

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

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

48 

49The [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.

50 

51During 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.

52 

53## Example: build a webhook receiver

54 

55This 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.

56 

57This 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).

58 

59<Steps>

60 <Step title="Create the project">

61 Create a new directory and install the MCP SDK:

62 

63 ```bash theme={null}

64 mkdir webhook-channel && cd webhook-channel

65 bun add @modelcontextprotocol/sdk

66 ```

67 </Step>

68 

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

70 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.

71 

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

73 #!/usr/bin/env bun

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

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

76 

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

78 const mcp = new Server(

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

80 {

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

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

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

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

85 },

86 )

87 

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

89 await mcp.connect(new StdioServerTransport())

90 

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

92 Bun.serve({

93 port: 8788, // any open port works

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

95 hostname: '127.0.0.1',

96 async fetch(req) {

97 const body = await req.text()

98 await mcp.notification({

99 method: 'notifications/claude/channel',

100 params: {

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

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

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

104 },

105 })

106 return new Response('ok')

107 },

108 })

109 ```

110 

111 The file does three things in order:

112 

113 * **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.

114 * **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.

115 * **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.

116 </Step>

117 

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

119 Add the server to your MCP config so Claude Code knows how to start it. For a project-level `.mcp.json` in the same directory, use a relative path. For user-level config in `~/.claude.json`, use the full absolute path so the server can be found from any project:

120 

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

122 {

123 "mcpServers": {

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

125 }

126 }

127 ```

128 

129 Claude Code reads your MCP config at startup and spawns each server as a subprocess.

130 </Step>

131 

132 <Step title="Test it">

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

134 

135 ```bash theme={null}

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

137 ```

138 

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

140 

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

142 

143 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):

144 

145 ```bash theme={null}

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

147 ```

148 

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

150 

151 ```text theme={null}

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

153 ```

154 

155 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).

156 

157 If the event doesn't arrive, the diagnosis depends on what `curl` returned:

158 

159 * **`curl` succeeds but nothing reaches Claude**: run `/mcp` in your session to check the server's status. "Failed to connect" usually means a dependency or import error in your server file; check the debug log at `~/.claude/debug/<session-id>.txt` for the stderr trace.

160 * **`curl` fails with "connection refused"**: the port is either not bound yet or a stale process from an earlier run is holding it. `lsof -i :<port>` shows what's listening; `kill` the stale process before restarting your session.

161 </Step>

162</Steps>

163 

164The [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.

165 

166## Test during the research preview

167 

168During 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:

169 

170```bash theme={null}

171# Testing a plugin you're developing

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

173 

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

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

176```

177 

178The 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.

179 

180<Note>

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

182</Note>

183 

184## Server options

185 

186A 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']` and `capabilities.experimental['claude/channel/permission']` are the channel-specific additions:

187 

188| Field | Type | Description |

189| :------------------------------------------------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

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

191| `capabilities.experimental['claude/channel/permission']` | `object` | Optional. Always `{}`. Declares that this channel can receive permission relay requests. When declared, Claude Code forwards tool approval prompts to your channel so you can approve or deny them remotely. See [Relay permission prompts](#relay-permission-prompts). |

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

193| `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`). |

194 

195To create a one-way channel, omit `capabilities.tools`. This example shows a two-way setup with the channel capability, tools, and instructions set:

196 

197```ts theme={null}

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

199 

200const mcp = new Server(

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

202 {

203 capabilities: {

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

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

206 },

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

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

209 },

210)

211```

212 

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

214 

215## Notification format

216 

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

218 

219| Field | Type | Description |

220| :-------- | :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

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

222| `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. |

223 

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

225 

226```ts theme={null}

227await mcp.notification({

228 method: 'notifications/claude/channel',

229 params: {

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

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

232 },

233})

234```

235 

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

237 

238```text theme={null}

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

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

241</channel>

242```

243 

244## Expose a reply tool

245 

246If 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:

247 

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

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

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

251 

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

253 

254<Steps>

255 <Step title="Enable tool discovery">

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

257 

258 ```ts theme={null}

259 capabilities: {

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

261 tools: {}, // enables tool discovery

262 },

263 ```

264 </Step>

265 

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

267 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`:

268 

269 ```ts theme={null}

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

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

272 

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

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

275 tools: [{

276 name: 'reply',

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

278 // inputSchema tells Claude what arguments to pass

279 inputSchema: {

280 type: 'object',

281 properties: {

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

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

284 },

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

286 },

287 }],

288 }))

289 

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

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

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

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

294 // send() is your outbound: POST to your chat platform, or for local

295 // testing the SSE broadcast shown in the full example below.

296 send(`Reply to ${chat_id}: ${text}`)

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

298 }

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

300 })

301 ```

302 </Step>

303 

304 <Step title="Update the instructions">

305 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:

306 

307 ```ts theme={null}

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

309 ```

310 </Step>

311</Steps>

312 

313Here's the complete `webhook.ts` with two-way support. Outbound replies stream over `GET /events` using [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) (SSE), so `curl -N localhost:8788/events` can watch them live; inbound chat arrives on `POST /`:

314 

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

316#!/usr/bin/env bun

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

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

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

320 

321// --- Outbound: write to any curl -N listeners on /events --------------------

322// A real bridge would POST to your chat platform instead.

323const listeners = new Set<(chunk: string) => void>()

324function send(text: string) {

325 const chunk = text.split('\n').map(l => `data: ${l}\n`).join('') + '\n'

326 for (const emit of listeners) emit(chunk)

327}

328 

329const mcp = new Server(

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

331 {

332 capabilities: {

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

334 tools: {},

335 },

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

337 },

338)

339 

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

341 tools: [{

342 name: 'reply',

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

344 inputSchema: {

345 type: 'object',

346 properties: {

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

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

349 },

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

351 },

352 }],

353}))

354 

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

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

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

358 send(`Reply to ${chat_id}: ${text}`)

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

360 }

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

362})

363 

364await mcp.connect(new StdioServerTransport())

365 

366let nextId = 1

367Bun.serve({

368 port: 8788,

369 hostname: '127.0.0.1',

370 idleTimeout: 0, // don't close idle SSE streams

371 async fetch(req) {

372 const url = new URL(req.url)

373 

374 // GET /events: SSE stream so curl -N can watch Claude's replies live

375 if (req.method === 'GET' && url.pathname === '/events') {

376 const stream = new ReadableStream({

377 start(ctrl) {

378 ctrl.enqueue(': connected\n\n') // so curl shows something immediately

379 const emit = (chunk: string) => ctrl.enqueue(chunk)

380 listeners.add(emit)

381 req.signal.addEventListener('abort', () => listeners.delete(emit))

382 },

383 })

384 return new Response(stream, {

385 headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' },

386 })

387 }

388 

389 // POST: forward to Claude as a channel event

390 const body = await req.text()

391 const chat_id = String(nextId++)

392 await mcp.notification({

393 method: 'notifications/claude/channel',

394 params: {

395 content: body,

396 meta: { chat_id, path: url.pathname, method: req.method },

397 },

398 })

399 return new Response('ok')

400 },

401})

402```

403 

404The [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.

405 

406## Gate inbound messages

407 

408An 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.

409 

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

411 

412```ts theme={null}

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

414 

415// inside your message handler, before emitting:

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

417 return // drop silently

418}

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

420```

421 

422Gate 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.

423 

424The [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. The [iMessage](https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/imessage) channel takes a different approach: it detects the user's own addresses from the Messages database at startup and lets them through automatically, with other senders added by handle.

425 

426## Relay permission prompts

427 

428<Note>

429 Permission relay requires Claude Code v2.1.81 or later. Earlier versions ignore the `claude/channel/permission` capability.

430</Note>

431 

432When Claude calls a tool that needs approval, the local terminal dialog opens and the session waits. A two-way channel can opt in to receive the same prompt in parallel and relay it to you on another device. Both stay live: you can answer in the terminal or on your phone, and Claude Code applies whichever answer arrives first and closes the other.

433 

434Relay covers tool-use approvals like `Bash`, `Write`, and `Edit`. Project trust and MCP server consent dialogs don't relay; those only appear in the local terminal.

435 

436### How relay works

437 

438When a permission prompt opens, the relay loop has four steps:

439 

4401. Claude Code generates a short request ID and notifies your server

4412. Your server forwards the prompt and ID to your chat app

4423. The remote user replies with a yes or no and that ID

4434. Your inbound handler parses the reply into a verdict, and Claude Code applies it only if the ID matches an open request

444 

445The local terminal dialog stays open through all of this. If someone at the terminal answers before the remote verdict arrives, that answer is applied instead and the pending remote request is dropped.

446 

447<img src="https://mintcdn.com/claude-code/DsZvsJII1OmzIjIs/en/images/channel-permission-relay.svg?fit=max&auto=format&n=DsZvsJII1OmzIjIs&q=85&s=c1d75f6ee34c2757983e2cca899b90d1" alt="Sequence diagram: Claude Code sends a permission_request notification to the channel server, the server formats and sends the prompt to the chat app, the human replies with a verdict, and the server parses that reply into a permission notification back to Claude Code" width="600" height="230" data-path="en/images/channel-permission-relay.svg" />

448 

449### Permission request fields

450 

451The outbound notification from Claude Code is `notifications/claude/channel/permission_request`. Like the [channel notification](#notification-format), the transport is standard MCP but the method and schema are Claude Code extensions. The `params` object has four string fields your server formats into the outgoing prompt:

452 

453| Field | Description |

454| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

455| `request_id` | Five lowercase letters drawn from `a`-`z` without `l`, so it never reads as a `1` or `I` when typed on a phone. Include it in your outgoing prompt so it can be echoed in the reply. Claude Code only accepts a verdict that carries an ID it issued. The local terminal dialog doesn't display this ID, so your outbound handler is the only way to learn it. |

456| `tool_name` | Name of the tool Claude wants to use, for example `Bash` or `Write`. |

457| `description` | Human-readable summary of what this specific tool call does, the same text the local terminal dialog shows. For a Bash call this is Claude's description of the command, or the command itself if none was given. |

458| `input_preview` | The tool's arguments as a JSON string, truncated to 200 characters. For Bash this is the command; for Write it's the file path and a prefix of the content. Omit it from your prompt if you only have room for a one-line message. Your server decides what to show. |

459 

460The verdict your server sends back is `notifications/claude/channel/permission` with two fields: `request_id` echoing the ID above, and `behavior` set to `'allow'` or `'deny'`. Allow lets the tool call proceed; deny rejects it, the same as answering No in the local dialog. Neither verdict affects future calls.

461 

462### Add relay to a chat bridge

463 

464Adding permission relay to a two-way channel takes three components:

465 

4661. A `claude/channel/permission: {}` entry under `experimental` capabilities in your `Server` constructor so Claude Code knows to forward prompts

4672. A notification handler for `notifications/claude/channel/permission_request` that formats the prompt and sends it out through your platform API

4683. A check in your inbound message handler that recognizes `yes <id>` or `no <id>` and emits a `notifications/claude/channel/permission` verdict instead of forwarding the text to Claude

469 

470Only declare the capability if your channel [authenticates the sender](#gate-inbound-messages), because anyone who can reply through your channel can approve or deny tool use in your session.

471 

472To add these to a two-way chat bridge like the one assembled in [Expose a reply tool](#expose-a-reply-tool):

473 

474<Steps>

475 <Step title="Declare the permission capability">

476 In your `Server` constructor, add `claude/channel/permission: {}` alongside `claude/channel` under `experimental`:

477 

478 ```ts theme={null}

479 capabilities: {

480 experimental: {

481 'claude/channel': {},

482 'claude/channel/permission': {}, // opt in to permission relay

483 },

484 tools: {},

485 },

486 ```

487 </Step>

488 

489 <Step title="Handle the incoming request">

490 Register a notification handler between your `Server` constructor and `mcp.connect()`. Claude Code calls it with the [four request fields](#permission-request-fields) when a permission dialog opens. Your handler formats the prompt for your platform and includes instructions for replying with the ID:

491 

492 ```ts theme={null}

493 import { z } from 'zod'

494 

495 // setNotificationHandler routes by z.literal on the method field,

496 // so this schema is both the validator and the dispatch key

497 const PermissionRequestSchema = z.object({

498 method: z.literal('notifications/claude/channel/permission_request'),

499 params: z.object({

500 request_id: z.string(), // five lowercase letters, include verbatim in your prompt

501 tool_name: z.string(), // e.g. "Bash", "Write"

502 description: z.string(), // human-readable summary of this call

503 input_preview: z.string(), // tool args as JSON, truncated to ~200 chars

504 }),

505 })

506 

507 mcp.setNotificationHandler(PermissionRequestSchema, async ({ params }) => {

508 // send() is your outbound: POST to your chat platform, or for local

509 // testing the SSE broadcast shown in the full example below.

510 send(

511 `Claude wants to run ${params.tool_name}: ${params.description}\n\n` +

512 // the ID in the instruction is what your inbound handler parses in Step 3

513 `Reply "yes ${params.request_id}" or "no ${params.request_id}"`,

514 )

515 })

516 ```

517 </Step>

518 

519 <Step title="Intercept the verdict in your inbound handler">

520 Your inbound handler is the loop or callback that receives messages from your platform: the same place you [gate on sender](#gate-inbound-messages) and emit `notifications/claude/channel` to forward chat to Claude. Add a check before the chat-forwarding call that recognizes the verdict format and emits the permission notification instead.

521 

522 The regex matches the ID format Claude Code generates: five letters, never `l`. The `/i` flag tolerates phone autocorrect capitalizing the reply; lowercase the captured ID before sending it back.

523 

524 ```ts theme={null}

525 // matches "y abcde", "yes abcde", "n abcde", "no abcde"

526 // [a-km-z] is the ID alphabet Claude Code uses (lowercase, skips 'l')

527 // /i tolerates phone autocorrect; lowercase the capture before sending

528 const PERMISSION_REPLY_RE = /^\s*(y|yes|n|no)\s+([a-km-z]{5})\s*$/i

529 

530 async function onInbound(message: PlatformMessage) {

531 if (!allowed.has(message.from.id)) return // gate on sender first

532 

533 const m = PERMISSION_REPLY_RE.exec(message.text)

534 if (m) {

535 // m[1] is the verdict word, m[2] is the request ID

536 // emit the verdict notification back to Claude Code instead of chat

537 await mcp.notification({

538 method: 'notifications/claude/channel/permission',

539 params: {

540 request_id: m[2].toLowerCase(), // normalize in case of autocorrect caps

541 behavior: m[1].toLowerCase().startsWith('y') ? 'allow' : 'deny',

542 },

543 })

544 return // handled as verdict, don't also forward as chat

545 }

546 

547 // didn't match verdict format: fall through to the normal chat path

548 await mcp.notification({

549 method: 'notifications/claude/channel',

550 params: { content: message.text, meta: { chat_id: String(message.chat.id) } },

551 })

552 }

553 ```

554 </Step>

555</Steps>

556 

557Claude Code also keeps the local terminal dialog open, so you can answer in either place, and the first answer to arrive is applied. A remote reply that doesn't exactly match the expected format fails in one of two ways, and in both cases the dialog stays open:

558 

559* **Different format**: your inbound handler's regex fails to match, so text like `approve it` or `yes` without an ID falls through as a normal message to Claude.

560* **Right format, wrong ID**: your server emits a verdict, but Claude Code finds no open request with that ID and drops it silently.

561 

562### Full example

563 

564The assembled `webhook.ts` below combines all three extensions from this page: the reply tool, sender gating, and permission relay. If you're starting here, you'll also need the [project setup and `.mcp.json` entry](#example-build-a-webhook-receiver) from the initial walkthrough.

565 

566To make both directions testable from curl, the HTTP listener serves two paths:

567 

568* **`GET /events`**: holds an SSE stream open and pushes each outbound message as a `data:` line, so `curl -N` can watch Claude's replies and permission prompts arrive live.

569* **`POST /`**: the inbound side, the same handler as earlier, now with the verdict-format check inserted before the chat-forward branch.

570 

571```ts title="Full webhook.ts with permission relay" expandable theme={null}

572#!/usr/bin/env bun

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

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

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

576import { z } from 'zod'

577 

578// --- Outbound: write to any curl -N listeners on /events --------------------

579// A real bridge would POST to your chat platform instead.

580const listeners = new Set<(chunk: string) => void>()

581function send(text: string) {

582 const chunk = text.split('\n').map(l => `data: ${l}\n`).join('') + '\n'

583 for (const emit of listeners) emit(chunk)

584}

585 

586// Sender allowlist. For the local walkthrough we trust the single X-Sender

587// header value "dev"; a real bridge would check the platform's user ID.

588const allowed = new Set(['dev'])

589 

590const mcp = new Server(

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

592 {

593 capabilities: {

594 experimental: {

595 'claude/channel': {},

596 'claude/channel/permission': {}, // opt in to permission relay

597 },

598 tools: {},

599 },

600 instructions:

601 'Messages arrive as <channel source="webhook" chat_id="...">. ' +

602 'Reply with the reply tool, passing the chat_id from the tag.',

603 },

604)

605 

606// --- reply tool: Claude calls this to send a message back -------------------

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

608 tools: [{

609 name: 'reply',

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

611 inputSchema: {

612 type: 'object',

613 properties: {

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

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

616 },

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

618 },

619 }],

620}))

621 

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

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

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

625 send(`Reply to ${chat_id}: ${text}`)

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

627 }

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

629})

630 

631// --- permission relay: Claude Code (not Claude) calls this when a dialog opens

632const PermissionRequestSchema = z.object({

633 method: z.literal('notifications/claude/channel/permission_request'),

634 params: z.object({

635 request_id: z.string(),

636 tool_name: z.string(),

637 description: z.string(),

638 input_preview: z.string(),

639 }),

640})

641 

642mcp.setNotificationHandler(PermissionRequestSchema, async ({ params }) => {

643 send(

644 `Claude wants to run ${params.tool_name}: ${params.description}\n\n` +

645 `Reply "yes ${params.request_id}" or "no ${params.request_id}"`,

646 )

647})

648 

649await mcp.connect(new StdioServerTransport())

650 

651// --- HTTP on :8788: GET /events streams outbound, POST routes inbound -------

652const PERMISSION_REPLY_RE = /^\s*(y|yes|n|no)\s+([a-km-z]{5})\s*$/i

653let nextId = 1

654 

655Bun.serve({

656 port: 8788,

657 hostname: '127.0.0.1',

658 idleTimeout: 0, // don't close idle SSE streams

659 async fetch(req) {

660 const url = new URL(req.url)

661 

662 // GET /events: SSE stream so curl -N can watch replies and prompts live

663 if (req.method === 'GET' && url.pathname === '/events') {

664 const stream = new ReadableStream({

665 start(ctrl) {

666 ctrl.enqueue(': connected\n\n') // so curl shows something immediately

667 const emit = (chunk: string) => ctrl.enqueue(chunk)

668 listeners.add(emit)

669 req.signal.addEventListener('abort', () => listeners.delete(emit))

670 },

671 })

672 return new Response(stream, {

673 headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' },

674 })

675 }

676 

677 // everything else is inbound: gate on sender first

678 const body = await req.text()

679 const sender = req.headers.get('X-Sender') ?? ''

680 if (!allowed.has(sender)) return new Response('forbidden', { status: 403 })

681 

682 // check for verdict format before treating as chat

683 const m = PERMISSION_REPLY_RE.exec(body)

684 if (m) {

685 await mcp.notification({

686 method: 'notifications/claude/channel/permission',

687 params: {

688 request_id: m[2].toLowerCase(),

689 behavior: m[1].toLowerCase().startsWith('y') ? 'allow' : 'deny',

690 },

691 })

692 return new Response('verdict recorded')

693 }

694 

695 // normal chat: forward to Claude as a channel event

696 const chat_id = String(nextId++)

697 await mcp.notification({

698 method: 'notifications/claude/channel',

699 params: { content: body, meta: { chat_id, path: url.pathname } },

700 })

701 return new Response('ok')

702 },

703})

704```

705 

706Test the verdict path in three terminals. The first is your Claude Code session, started with the [development flag](#test-during-the-research-preview) so it spawns `webhook.ts`:

707 

708```bash theme={null}

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

710```

711 

712In the second, stream the outbound side so you can see Claude's replies and any permission prompts as they fire:

713 

714```bash theme={null}

715curl -N localhost:8788/events

716```

717 

718In the third, send a message that will make Claude try to run a command:

719 

720```bash theme={null}

721curl -d "list the files in this directory" -H "X-Sender: dev" localhost:8788

722```

723 

724The local permission dialog opens in your Claude Code terminal. A moment later the prompt appears in the `/events` stream, including the five-letter ID. Approve it from the remote side:

725 

726```bash theme={null}

727curl -d "yes <id>" -H "X-Sender: dev" localhost:8788

728```

729 

730The local dialog closes and the tool runs. Claude's reply comes back through the `reply` tool and lands in the stream too.

731 

732The three channel-specific pieces in this file:

733 

734* **Capabilities** in the `Server` constructor: `claude/channel` registers the notification listener, `claude/channel/permission` opts in to permission relay, `tools` lets Claude discover the reply tool.

735* **Outbound paths**: the `reply` tool handler is what Claude calls for conversational responses; the `PermissionRequestSchema` notification handler is what Claude Code calls when a permission dialog opens. Both call `send()` to broadcast over `/events`, but they're triggered by different parts of the system.

736* **HTTP handler**: `GET /events` holds an SSE stream open so curl can watch outbound live; `POST` is inbound, gated on the `X-Sender` header. A `yes <id>` or `no <id>` body goes to Claude Code as a verdict notification and never reaches Claude; anything else is forwarded to Claude as a channel event.

737 

738## Package as a plugin

739 

740To 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>`.

741 

742A 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. On Team and Enterprise plans, an admin can instead include your plugin in the organization's own [`allowedChannelPlugins`](/en/channels#restrict-which-channel-plugins-can-run) list, which replaces the default Anthropic allowlist.

743 

744## See also

745 

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

747* [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

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

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

checkpointing.md +30 −10

Details

4 4 

5# Checkpointing5# Checkpointing

6 6 

7> Automatically track and rewind Claude's edits to quickly recover from unwanted changes.7> Track, rewind, and summarize Claude's edits and conversation to manage session state.

8 8 

9Claude Code automatically tracks Claude's file edits as you work, allowing you to quickly undo changes and rewind to previous states if anything gets off track.9Claude Code automatically tracks Claude's file edits as you work, allowing you to quickly undo changes and rewind to previous states if anything gets off track.

10 10 


20* Checkpoints persist across sessions, so you can access them in resumed conversations20* Checkpoints persist across sessions, so you can access them in resumed conversations

21* Automatically cleaned up along with sessions after 30 days (configurable)21* Automatically cleaned up along with sessions after 30 days (configurable)

22 22 

23### Rewinding changes23### Rewind and summarize

24 24 

25Press `Esc` twice (`Esc` + `Esc`) or use the `/rewind` command to open up the rewind menu. You can choose to restore:25Press `Esc` twice (`Esc` + `Esc`) or use the `/rewind` command to open the rewind menu. A scrollable list shows each of your prompts from the session. Select the point you want to act on, then choose an action:

26 26 

27* **Conversation only**: Rewind to a user message while keeping code changes27* **Restore code and conversation**: revert both code and conversation to that point

28* **Code only**: Revert file changes while keeping the conversation28* **Restore conversation**: rewind to that message while keeping current code

29* **Both code and conversation**: Restore both to a prior point in the session29* **Restore code**: revert file changes while keeping the conversation

30* **Summarize from here**: compress the conversation from this point forward into a summary, freeing context window space

31* **Never mind**: return to the message list without making changes

32 

33After restoring the conversation or summarizing, the original prompt from the selected message is restored into the input field so you can re-send or edit it.

34 

35#### Restore vs. summarize

36 

37The three restore options revert state: they undo code changes, conversation history, or both. "Summarize from here" works differently:

38 

39* Messages before the selected message stay intact

40* The selected message and all subsequent messages get replaced with a compact AI-generated summary

41* No files on disk are changed

42* The original messages are preserved in the session transcript, so Claude can reference the details if needed

43 

44This is similar to `/compact`, but targeted: instead of summarizing the entire conversation, you keep early context in full detail and only compress the parts that are using up space. You can type optional instructions to guide what the summary focuses on.

45 

46<Note>

47 Summarize keeps you in the same session and compresses context. If you want to branch off and try a different approach while preserving the original session intact, use [fork](/en/how-claude-code-works#resume-or-fork-sessions) instead (`claude --continue --fork-session`).

48</Note>

30 49 

31## Common use cases50## Common use cases

32 51 

33Checkpoints are particularly useful when:52Checkpoints are particularly useful when:

34 53 

35* **Exploring alternatives**: Try different implementation approaches without losing your starting point54* **Exploring alternatives**: try different implementation approaches without losing your starting point

36* **Recovering from mistakes**: Quickly undo changes that introduced bugs or broke functionality55* **Recovering from mistakes**: quickly undo changes that introduced bugs or broke functionality

37* **Iterating on features**: Experiment with variations knowing you can revert to working states56* **Iterating on features**: experiment with variations knowing you can revert to working states

57* **Freeing context space**: summarize a verbose debugging session from the midpoint forward, keeping your initial instructions intact

38 58 

39## Limitations59## Limitations

40 60 


65## See also85## See also

66 86 

67* [Interactive mode](/en/interactive-mode) - Keyboard shortcuts and session controls87* [Interactive mode](/en/interactive-mode) - Keyboard shortcuts and session controls

68* [Built-in commands](/en/interactive-mode#built-in-commands) - Accessing checkpoints using `/rewind`88* [Commands](/en/commands) - Accessing checkpoints using `/rewind`

69* [CLI reference](/en/cli-reference) - Command-line options89* [CLI reference](/en/cli-reference) - Command-line options

chrome.md +99 −86

Details

4 4 

5# Use Claude Code with Chrome (beta)5# Use Claude Code with Chrome (beta)

6 6 

7> Connect Claude Code to your browser to test web apps, debug with console logs, and automate browser tasks.7> Connect Claude Code to your Chrome browser to test web apps, debug with console logs, automate form filling, and extract data from web pages.

8 8 

9<Note>9Claude Code integrates with the [Claude in Chrome browser extension](https://chromewebstore.google.com/detail/claude/fcoeoabgfenejglbffodgkkbkcdhcgfn) to give you browser automation capabilities from the CLI or the [VS Code extension](/en/vs-code#automate-browser-tasks-with-chrome). Build your code, then test and debug in the browser without switching contexts.

10 Chrome integration is in beta and currently works with Google Chrome only. It is not yet supported on Brave, Arc, or other Chromium-based browsers. WSL (Windows Subsystem for Linux) is also not supported.

11</Note>

12 10 

13Claude Code integrates with the Claude in Chrome browser extension to give you browser automation capabilities directly from your terminal. Build in your terminal, then test and debug in your browser without switching contexts.11Claude opens new tabs for browser tasks and shares your browser's login state, so it can access any site you're already signed into. Browser actions run in a visible Chrome window in real time. When Claude encounters a login page or CAPTCHA, it pauses and asks you to handle it manually.

14 12 

15## What the integration enables13<Note>

14 Chrome integration is in beta and currently works with Google Chrome and Microsoft Edge. It is not yet supported on Brave, Arc, or other Chromium-based browsers. WSL (Windows Subsystem for Linux) is also not supported.

15</Note>

16 16 

17With Chrome connected, you can chain browser actions with terminal commands in a single workflow. For example: scrape documentation from a website, analyze it, generate code based on what you learned, and commit the result.17## Capabilities

18 18 

19Key capabilities include:19With Chrome connected, you can chain browser actions with coding tasks in a single workflow:

20 20 

21* **Live debugging**: Claude reads console errors and DOM state directly, then fixes the code that caused them21* **Live debugging**: read console errors and DOM state directly, then fix the code that caused them

22* **Design verification**: Build a UI from a Figma mock, then have Claude open it in the browser and verify it matches22* **Design verification**: build a UI from a Figma mock, then open it in the browser to verify it matches

23* **Web app testing**: Test form validation, check for visual regressions, or verify user flows work correctly23* **Web app testing**: test form validation, check for visual regressions, or verify user flows

24* **Authenticated web apps**: Interact with Google Docs, Gmail, Notion, or any app you're logged into without needing API connectors24* **Authenticated web apps**: interact with Google Docs, Gmail, Notion, or any app you're logged into without API connectors

25* **Data extraction**: Pull structured information from web pages and save it locally25* **Data extraction**: pull structured information from web pages and save it locally

26* **Task automation**: Automate repetitive browser tasks like data entry, form filling, or multi-site workflows26* **Task automation**: automate repetitive browser tasks like data entry, form filling, or multi-site workflows

27* **Session recording**: Record browser interactions as GIFs to document or share what happened27* **Session recording**: record browser interactions as GIFs to document or share what happened

28 28 

29## Prerequisites29## Prerequisites

30 30 

31Before using Claude Code with Chrome, you need:31Before using Claude Code with Chrome, you need:

32 32 

33* [Google Chrome](https://www.google.com/chrome/) browser33* [Google Chrome](https://www.google.com/chrome/) or [Microsoft Edge](https://www.microsoft.com/edge) browser

34* [Claude in Chrome extension](https://chromewebstore.google.com/detail/claude/fcoeoabgfenejglbffodgkkbkcdhcgfn) version 1.0.36 or higher34* [Claude in Chrome extension](https://chromewebstore.google.com/detail/claude/fcoeoabgfenejglbffodgkkbkcdhcgfn) version 1.0.36 or higher, available in the Chrome Web Store for both browsers

35* [Claude Code CLI](/en/quickstart#step-1-install-claude-code) version 2.0.73 or higher35* [Claude Code](/en/quickstart#step-1-install-claude-code) version 2.0.73 or higher

36* A paid Claude plan (Pro, Team, or Enterprise)36* A direct Anthropic plan (Pro, Max, Team, or Enterprise)

37 

38## How the integration works

39 

40Claude Code communicates with Chrome through the Claude in Chrome browser extension. The extension uses Chrome's [Native Messaging API](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging) to receive commands from Claude Code and execute them in your browser. This architecture lets Claude Code control browser tabs, read page content, and perform actions while you continue working in your terminal.

41 

42When Claude encounters a login page, CAPTCHA, or other blocker, it pauses and asks you to handle it. You can provide credentials for Claude to enter, or log in manually in the browser. Once you're past the blocker, tell Claude to continue and it picks up where it left off.

43 

44Claude opens new tabs for browser tasks rather than taking over existing ones. However, it shares your browser's login state, so if you're already signed into a site in Chrome, Claude can access it without re-authenticating.

45 37 

46<Note>38<Note>

47 The Chrome integration requires a visible browser window. When Claude performs browser actions, you'll see Chrome open and navigate in real time. There's no headless mode since the integration relies on your actual browser session with its login state.39 Chrome integration is not available through third-party providers like Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If you access Claude exclusively through a third-party provider, you need a separate claude.ai account to use this feature.

48</Note>40</Note>

49 41 

50## Set up the integration42## Get started in the CLI

51 43 

52<Steps>44<Steps>

53 <Step title="Update Claude Code">45 <Step title="Launch Claude Code with Chrome">

54 Chrome integration requires a recent version of Claude Code. If you installed using the [native installer](/en/quickstart#step-1-install-claude-code), updates happen automatically. Otherwise, run:46 Start Claude Code with the `--chrome` flag:

55 47 

56 ```bash theme={null}48 ```bash theme={null}

57 claude update49 claude --chrome

58 ```50 ```

51 

52 You can also enable Chrome from within an existing session by running `/chrome`.

59 </Step>53 </Step>

60 54 

61 <Step title="Start Claude Code with Chrome enabled">55 <Step title="Ask Claude to use the browser">

62 Launch Claude Code with the `--chrome` flag:56 This example navigates to a page, interacts with it, and reports what it finds, all from your terminal or editor:

63 57 

64 ```bash theme={null}58 ```text theme={null}

65 claude --chrome59 Go to code.claude.com/docs, click on the search box,

60 type "hooks", and tell me what results appear

66 ```61 ```

67 </Step>62 </Step>

68 

69 <Step title="Verify the connection">

70 Run `/chrome` to check the connection status and manage settings. If the extension isn't detected, you'll see a warning with a link to install it.

71 </Step>

72</Steps>63</Steps>

73 64 

74You can also enable Chrome integration from within an existing session using the `/chrome` command.65Run `/chrome` at any time to check the connection status, manage permissions, or reconnect the extension.

75 66 

76## Try it out67For VS Code, see [browser automation in VS Code](/en/vs-code#automate-browser-tasks-with-chrome).

77 68 

78Once connected, type this into Claude to see the integration in action:69### Enable Chrome by default

79 70 

80```71To avoid passing `--chrome` each session, run `/chrome` and select "Enabled by default".

81Go to code.claude.com/docs, click on the search box,

82type "hooks", and tell me what results appear

83```

84 72 

85Claude opens the page, clicks into the search field, types the query, and reports the autocomplete results. This shows navigation, clicking, and typing in a single workflow.73In the [VS Code extension](/en/vs-code#automate-browser-tasks-with-chrome), Chrome is available whenever the Chrome extension is installed. No additional flag is needed.

86 74 

87## Example workflows75<Note>

76 Enabling Chrome by default in the CLI increases context usage since browser tools are always loaded. If you notice increased context consumption, disable this setting and use `--chrome` only when needed.

77</Note>

78 

79### Manage site permissions

80 

81Site-level permissions are inherited from the Chrome extension. Manage permissions in the Chrome extension settings to control which sites Claude can browse, click, and type on.

88 82 

89Claude can navigate pages, click and type, fill forms, scroll, read console logs and network requests, manage tabs, resize windows, and record GIFs. Run `/mcp` and click into `claude-in-chrome` to see the full list of available tools.83## Example workflows

90 84 

91The following examples show common patterns for browser automation.85These examples show common ways to combine browser actions with coding tasks. Run `/mcp` and select `claude-in-chrome` to see the full list of available browser tools.

92 86 

93### Test a local web application87### Test a local web application

94 88 

95When developing a web app, ask Claude to verify your changes work correctly:89When developing a web app, ask Claude to verify your changes work correctly:

96 90 

97```91```text theme={null}

98I just updated the login form validation. Can you open localhost:3000,92I just updated the login form validation. Can you open localhost:3000,

99try submitting the form with invalid data, and check if the error93try submitting the form with invalid data, and check if the error

100messages appear correctly?94messages appear correctly?


104 98 

105### Debug with console logs99### Debug with console logs

106 100 

107If your app has issues, Claude can read console output to help diagnose problems:101Claude can read console output to help diagnose problems. Tell Claude what patterns to look for rather than asking for all console output, since logs can be verbose:

108 102 

109```103```text theme={null}

110Open the dashboard page and check the console for any errors when104Open the dashboard page and check the console for any errors when

111the page loads.105the page loads.

112```106```


117 111 

118Speed up repetitive data entry tasks:112Speed up repetitive data entry tasks:

119 113 

120```114```text theme={null}

121I have a spreadsheet of customer contacts in contacts.csv. For each row,115I have a spreadsheet of customer contacts in contacts.csv. For each row,

122go to our CRM at crm.example.com, click "Add Contact", and fill in the116go to the CRM at crm.example.com, click "Add Contact", and fill in the

123name, email, and phone fields.117name, email, and phone fields.

124```118```

125 119 


129 123 

130Use Claude to write directly in your documents without API setup:124Use Claude to write directly in your documents without API setup:

131 125 

132```126```text theme={null}

133Draft a project update based on our recent commits and add it to my127Draft a project update based on the recent commits and add it to my

134Google Doc at docs.google.com/document/d/abc123128Google Doc at docs.google.com/document/d/abc123

135```129```

136 130 


140 134 

141Pull structured information from websites:135Pull structured information from websites:

142 136 

143```137```text theme={null}

144Go to the product listings page and extract the name, price, and138Go to the product listings page and extract the name, price, and

145availability for each item. Save the results as a CSV file.139availability for each item. Save the results as a CSV file.

146```140```


151 145 

152Coordinate tasks across multiple websites:146Coordinate tasks across multiple websites:

153 147 

154```148```text theme={null}

155Check my calendar for meetings tomorrow, then for each meeting with149Check my calendar for meetings tomorrow, then for each meeting with

156an external attendee, look up their company on LinkedIn and add a150an external attendee, look up their company website and add a note

157note about what they do.151about what they do.

158```152```

159 153 

160Claude works across tabs to gather information and complete the workflow.154Claude works across tabs to gather information and complete the workflow.


163 157 

164Create shareable recordings of browser interactions:158Create shareable recordings of browser interactions:

165 159 

166```160```text theme={null}

167Record a GIF showing how to complete the checkout flow, from adding161Record a GIF showing how to complete the checkout flow, from adding

168an item to the cart through to the confirmation page.162an item to the cart through to the confirmation page.

169```163```

170 164 

171Claude records the interaction sequence and saves it as a GIF file.165Claude records the interaction sequence and saves it as a GIF file.

172 166 

173## Best practices

174 

175When using browser automation, keep these guidelines in mind:

176 

177* **Modal dialogs can interrupt the flow**: JavaScript alerts, confirms, and prompts block browser events and prevent Claude from receiving commands. If a dialog appears, dismiss it manually and tell Claude to continue.

178* **Use fresh tabs**: Claude creates new tabs for each session. If a tab becomes unresponsive, ask Claude to create a new one.

179* **Filter console output**: Console logs can be verbose. When debugging, tell Claude what patterns to look for rather than asking for all console output.

180 

181## Troubleshooting167## Troubleshooting

182 168 

183### Extension not detected169### Extension not detected

184 170 

185If Claude Code shows "Chrome extension not detected":171If Claude Code shows "Chrome extension not detected":

186 172 

1871. Verify the Chrome extension (version 1.0.36 or higher) is installed1731. Verify the Chrome extension is installed and enabled in `chrome://extensions`

1882. Verify Claude Code is version 2.0.73 or higher by running `claude --version`1742. Verify Claude Code is up to date by running `claude --version`

1893. Check that Chrome is running1753. Check that Chrome is running

1904. Run `/chrome` and select "Reconnect extension" to re-establish the connection1764. Run `/chrome` and select "Reconnect extension" to re-establish the connection

1915. If the issue persists, restart both Claude Code and Chrome1775. If the issue persists, restart both Claude Code and Chrome

192 178 

179The first time you enable Chrome integration, Claude Code installs a native messaging host configuration file. Chrome reads this file on startup, so if the extension isn't detected on your first attempt, restart Chrome to pick up the new configuration.

180 

181If the connection still fails, verify the host configuration file exists at:

182 

183For Chrome:

184 

185* **macOS**: `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json`

186* **Linux**: `~/.config/google-chrome/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json`

187* **Windows**: check `HKCU\Software\Google\Chrome\NativeMessagingHosts\` in the Windows Registry

188 

189For Edge:

190 

191* **macOS**: `~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json`

192* **Linux**: `~/.config/microsoft-edge/NativeMessagingHosts/com.anthropic.claude_code_browser_extension.json`

193* **Windows**: check `HKCU\Software\Microsoft\Edge\NativeMessagingHosts\` in the Windows Registry

194 

193### Browser not responding195### Browser not responding

194 196 

195If Claude's browser commands stop working:197If Claude's browser commands stop working:

196 198 

1971. Check if a modal dialog (alert, confirm, prompt) is blocking the page1991. Check if a modal dialog (alert, confirm, prompt) is blocking the page. JavaScript dialogs block browser events and prevent Claude from receiving commands. Dismiss the dialog manually, then tell Claude to continue.

1982. Ask Claude to create a new tab and try again2002. Ask Claude to create a new tab and try again

1993. Restart the Chrome extension by disabling and re-enabling it2013. Restart the Chrome extension by disabling and re-enabling it in `chrome://extensions`

200 202 

201### First-time setup203### Connection drops during long sessions

202 204 

203The first time you use the integration, Claude Code installs a native messaging host that allows communication between the CLI and Chrome. If you encounter permission errors, you may need to restart Chrome for the installation to take effect.205The Chrome extension's service worker can go idle during extended sessions, which breaks the connection. If browser tools stop working after a period of inactivity, run `/chrome` and select "Reconnect extension".

204 206 

205## Enable by default207### Windows-specific issues

206 208 

207Chrome integration requires the `--chrome` flag each time you start Claude Code. To enable it by default, run `/chrome` and select "Enabled by default".209On Windows, you may encounter:

208 210 

209<Note>211* **Named pipe conflicts (EADDRINUSE)**: if another process is using the same named pipe, restart Claude Code. Close any other Claude Code sessions that might be using Chrome.

210 Enabling Chrome by default increases context usage since browser tools are always loaded. If you notice increased context consumption, disable this setting and use `--chrome` only when needed.212* **Native messaging host errors**: if the native messaging host crashes on startup, try reinstalling Claude Code to regenerate the host configuration.

211</Note>213 

214### Common error messages

215 

216These are the most frequently encountered errors and how to resolve them:

212 217 

213Site-level permissions are inherited from the Chrome extension. Manage permissions in the Chrome extension settings to control which sites Claude can browse, click, and type on. Run `/chrome` to see current permission settings.218| Error | Cause | Fix |

219| ------------------------------------ | ------------------------------------------------ | --------------------------------------------------------------- |

220| "Browser extension is not connected" | Native messaging host cannot reach the extension | Restart Chrome and Claude Code, then run `/chrome` to reconnect |

221| "Extension not detected" | Chrome extension is not installed or is disabled | Install or enable the extension in `chrome://extensions` |

222| "No tab available" | Claude tried to act before a tab was ready | Ask Claude to create a new tab and retry |

223| "Receiving end does not exist" | Extension service worker went idle | Run `/chrome` and select "Reconnect extension" |

214 224 

215## See also225## See also

216 226 

217* [CLI reference](/en/cli-reference) - Command-line flags including `--chrome`227* [Computer use](/en/computer-use): control native macOS apps when a task can't be done in a browser

218* [Common workflows](/en/common-workflows) - More ways to use Claude Code228* [Use Claude Code in VS Code](/en/vs-code#automate-browser-tasks-with-chrome): browser automation in the VS Code extension

219* [Getting started with Claude for Chrome](https://support.anthropic.com/en/articles/12012173-getting-started-with-claude-for-chrome) - Full documentation for the Chrome extension, including shortcuts, scheduling, and permissions229* [CLI reference](/en/cli-reference): command-line flags including `--chrome`

230* [Common workflows](/en/common-workflows): more ways to use Claude Code

231* [Data and privacy](/en/data-usage): how Claude Code handles your data

232* [Getting started with Claude in Chrome](https://support.claude.com/en/articles/12012173-getting-started-with-claude-in-chrome): full documentation for the Chrome extension, including shortcuts, scheduling, and permissions

Details

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> 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.3> Use this file to discover all available pages before exploring further.

4 4 

5# Claude Code on the web5# Use Claude Code on the web

6 6 

7> Run Claude Code tasks asynchronously on secure cloud infrastructure7> Configure cloud environments, setup scripts, network access, and Docker in Anthropic's sandbox. Move sessions between web and terminal with `--remote` and `--teleport`.

8 8 

9<Note>9<Note>

10 Claude Code on the web is currently in research preview.10 Claude Code on the web is in research preview for Pro, Max, and Team users, and for Enterprise users with premium seats or Chat + Claude Code seats.

11</Note>11</Note>

12 12 

13## What is Claude Code on the web?13Claude Code on the web runs tasks on Anthropic-managed cloud infrastructure at [claude.ai/code](https://claude.ai/code). Sessions persist even if you close your browser, and you can monitor them from the Claude mobile app.

14 14 

15Claude Code on the web lets developers kick off Claude Code from the Claude app. This is perfect for:15<Tip>

16 New to Claude Code on the web? Start with [Get started](/en/web-quickstart) to connect your GitHub account and submit your first task.

17</Tip>

16 18 

17* **Answering questions**: Ask about code architecture and how features are implemented19This page covers:

18* **Bug fixes and routine tasks**: Well-defined tasks that don't require frequent steering

19* **Parallel work**: Tackle multiple bug fixes in parallel

20* **Repositories not on your local machine**: Work on code you don't have checked out locally

21* **Backend changes**: Where Claude Code can write tests and then write code to pass those tests

22 20 

23Claude Code is also available on the Claude iOS app for kicking off tasks on the go and monitoring work in progress.21* [GitHub authentication options](#github-authentication-options): two ways to connect GitHub

22* [The cloud environment](#the-cloud-environment): what config carries over, what tools are installed, and how to configure environments

23* [Setup scripts](#setup-scripts) and dependency management

24* [Network access](#network-access): levels, proxies, and the default allowlist

25* [Move tasks between web and terminal](#move-tasks-between-web-and-terminal) with `--remote` and `--teleport`

26* [Work with sessions](#work-with-sessions): reviewing, sharing, archiving, deleting

27* [Auto-fix pull requests](#auto-fix-pull-requests): respond automatically to CI failures and review comments

28* [Security and isolation](#security-and-isolation): how sessions are isolated

29* [Limitations](#limitations): rate limits and platform restrictions

24 30 

25You can move between local and remote development: [send tasks from your terminal to run on the web](#from-terminal-to-web) with the `&` prefix, or [teleport web sessions back to your terminal](#from-web-to-terminal) to continue locally.31## GitHub authentication options

26 32 

27## Who can use Claude Code on the web?33Cloud sessions need access to your GitHub repositories to clone code and push branches. You can grant access in two ways:

28 34 

29Claude Code on the web is available in research preview to:35| Method | How it works | Best for |

36| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------- |

37| **GitHub App** | Install the Claude GitHub App on specific repositories during [web onboarding](/en/web-quickstart). Access is scoped per repository. | Teams that want explicit per-repo authorization |

38| **`/web-setup`** | Run `/web-setup` in your terminal to sync your local `gh` CLI token to your Claude account. Access matches whatever your `gh` token can see. | Individual developers who already use `gh` |

30 39 

31* **Pro users**40Either method works. [`/schedule`](/en/routines) checks for either form of access and prompts you to run `/web-setup` if neither is configured. See [Connect from your terminal](/en/web-quickstart#connect-from-your-terminal) for the `/web-setup` walkthrough.

32* **Max users**

33* **Team premium seat users**

34* **Enterprise premium seat users**

35 41 

36## Getting started42The GitHub App is required for [Auto-fix](#auto-fix-pull-requests), which uses the App to receive PR webhooks. If you connect with `/web-setup` and later want Auto-fix, install the App on those repositories.

37 43 

381. Visit [claude.ai/code](https://claude.ai/code)44Team and Enterprise admins can disable `/web-setup` with the Quick web setup toggle at [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code).

392. Connect your GitHub account

403. Install the Claude GitHub app in your repositories

414. Select your default environment

425. Submit your coding task

436. Review changes in diff view, iterate with comments, then create a pull request

44 45 

45## How it works46<Note>

47 Organizations with [Zero Data Retention](/en/zero-data-retention) enabled cannot use `/web-setup` or other cloud session features.

48</Note>

46 49 

47When you start a task on Claude Code on the web:50## The cloud environment

48 51 

491. **Repository cloning**: Your repository is cloned to an Anthropic-managed virtual machine52Each session runs in a fresh Anthropic-managed VM with your repository cloned. This section covers what's available when a session starts and how to customize it.

502. **Environment setup**: Claude prepares a secure cloud environment with your code

513. **Network configuration**: Internet access is configured based on your settings

524. **Task execution**: Claude analyzes code, makes changes, runs tests, and checks its work

535. **Completion**: You're notified when finished and can create a PR with the changes

546. **Results**: Changes are pushed to a branch, ready for pull request creation

55 53 

56## Review changes with diff view54### What's available in cloud sessions

57 55 

58Diff view lets you see exactly what Claude changed before creating a pull request. Instead of clicking "Create PR" to review changes in GitHub, view the diff directly in the app and iterate with Claude until the changes are ready.56Cloud sessions start from a fresh clone of your repository. Anything committed to the repo is available. Anything you've installed or configured only on your own machine is not.

59 57 

60When Claude makes changes to files, a diff stats indicator appears showing the number of lines added and removed (for example, `+12 -1`). Select this indicator to open the diff viewer, which displays a file list on the left and the changes for each file on the right.58| | Available in cloud sessions | Why |

59| :-------------------------------------------------------------------- | :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- |

60| Your repo's `CLAUDE.md` | Yes | Part of the clone |

61| Your repo's `.claude/settings.json` hooks | Yes | Part of the clone |

62| Your repo's `.mcp.json` MCP servers | Yes | Part of the clone |

63| Your repo's `.claude/rules/` | Yes | Part of the clone |

64| Your repo's `.claude/skills/`, `.claude/agents/`, `.claude/commands/` | Yes | Part of the clone |

65| Plugins declared in `.claude/settings.json` | Yes | Installed at session start from the [marketplace](/en/plugin-marketplaces) you declared. Requires network access to reach the marketplace source |

66| Your user `~/.claude/CLAUDE.md` | No | Lives on your machine, not in the repo |

67| Plugins enabled only in your user settings | No | User-scoped `enabledPlugins` lives in `~/.claude/settings.json`. Declare them in the repo's `.claude/settings.json` instead |

68| MCP servers you added with `claude mcp add` | No | Those write to your local user config, not the repo. Declare the server in [`.mcp.json`](/en/mcp#project-scope) instead |

69| Static API tokens and credentials | No | No dedicated secrets store exists yet. See below |

70| Interactive auth like AWS SSO | No | Not supported. SSO requires browser-based login that can't run in a cloud session |

61 71 

62From the diff view, you can:72To make configuration available in cloud sessions, commit it to the repo. A dedicated secrets store is not yet available. Both environment variables and setup scripts are stored in the environment configuration, visible to anyone who can edit that environment. If you need secrets in a cloud session, add them as environment variables with that visibility in mind.

63 73 

64* Review changes file by file74### Installed tools

65* Comment on specific changes to request modifications

66* Continue iterating with Claude based on what you see

67 75 

68This lets you refine changes through multiple rounds of feedback without creating draft PRs or switching to GitHub.76Cloud sessions come with common language runtimes, build tools, and databases pre-installed. The table below summarizes what's included by category.

69 77 

70## Moving tasks between web and terminal78| Category | Included |

79| :------------ | :--------------------------------------------------------------------------------- |

80| **Python** | Python 3.x with pip, poetry, uv, black, mypy, pytest, ruff |

81| **Node.js** | 20, 21, and 22 via nvm, with npm, yarn, pnpm, bun¹, eslint, prettier, chromedriver |

82| **Ruby** | 3.1, 3.2, 3.3 with gem, bundler, rbenv |

83| **PHP** | 8.4 with Composer |

84| **Java** | OpenJDK 21 with Maven and Gradle |

85| **Go** | latest stable with module support |

86| **Rust** | rustc and cargo |

87| **C/C++** | GCC, Clang, cmake, ninja, conan |

88| **Docker** | docker, dockerd, docker compose |

89| **Databases** | PostgreSQL 16, Redis 7.0 |

90| **Utilities** | git, jq, yq, ripgrep, tmux, vim, nano |

71 91 

72You can start tasks on the web and continue them in your terminal, or send tasks from your terminal to run on the web. Web sessions persist even if you close your laptop, and you can monitor them from anywhere including the Claude iOS app.92¹ Bun is installed but has known [proxy compatibility issues](#install-dependencies-with-a-sessionstart-hook) for package fetching.

73 93 

74<Note>94For exact versions, ask Claude to run `check-tools` in a cloud session. This command only exists in cloud sessions.

75 Session handoff is one-way: you can pull web sessions into your terminal, but you can't push an existing terminal session to the web. The [`&` prefix](#from-terminal-to-web) creates a *new* web session with your current conversation context.

76</Note>

77 95 

78### From terminal to web96### Work with GitHub issues and pull requests

79 97 

80Start a message with `&` inside Claude Code to send a task to run on the web:98Cloud sessions include built-in GitHub tools that let Claude read issues, list pull requests, fetch diffs, and post comments without any setup. These tools authenticate through the [GitHub proxy](#github-proxy) using whichever method you configured under [GitHub authentication options](#github-authentication-options), so your token never enters the container.

81 99 

82```100The `gh` CLI is not pre-installed. If you need a `gh` command the built-in tools don't cover, like `gh release` or `gh workflow run`, install and authenticate it yourself:

83& Fix the authentication bug in src/auth/login.ts

84```

85 101 

86This creates a new web session on claude.ai with your current conversation context. The task runs in the cloud while you continue working locally. Use `/tasks` to check progress, or open the session on claude.ai or the Claude iOS app to interact directly. From there you can steer Claude, provide feedback, or answer questions just like any other conversation.102<Steps>

103 <Step title="Install gh in your setup script">

104 Add `apt update && apt install -y gh` to your [setup script](#setup-scripts).

105 </Step>

87 106 

88You can also start a web session directly from the command line:107 <Step title="Provide a token">

108 Add a `GH_TOKEN` environment variable to your [environment settings](#configure-your-environment) with a GitHub personal access token. `gh` reads `GH_TOKEN` automatically, so no `gh auth login` step is needed.

109 </Step>

110</Steps>

89 111 

90```bash theme={null}112### Link artifacts back to the session

91claude --remote "Fix the authentication bug in src/auth/login.ts"

92```

93 113 

94#### Tips for background tasks114Each cloud session has a transcript URL on claude.ai, and the session can read its own ID from the `CLAUDE_CODE_REMOTE_SESSION_ID` environment variable. Use this to put a traceable link in PR bodies, commit messages, Slack posts, or generated reports so a reviewer can open the run that produced them.

95 115 

96**Plan locally, execute remotely**: For complex tasks, start Claude in plan mode to collaborate on the approach before sending work to the web:116Ask Claude to construct the link from the environment variable. The following command prints the URL:

97 117 

98```bash theme={null}118```bash theme={null}

99claude --permission-mode plan119echo "https://claude.ai/code/${CLAUDE_CODE_REMOTE_SESSION_ID}"

100```120```

101 121 

102In plan mode, Claude can only read files and explore the codebase. Once you're satisfied with the plan, send it to the web for autonomous execution:122### Run tests, start services, and add packages

103 123 

104```124Claude runs tests as part of working on a task. Ask for it in your prompt, like "fix the failing tests in `tests/`" or "run pytest after each change." Test runners like pytest, jest, and cargo test work out of the box since they're pre-installed.

105& Execute the migration plan we discussed

106```

107 

108This pattern gives you control over the strategy while letting Claude execute autonomously in the cloud.

109 125 

110**Run tasks in parallel**: Each `&` command creates its own web session that runs independently. You can kick off multiple tasks and they'll all run simultaneously in separate sessions:126PostgreSQL and Redis are pre-installed but not running by default. Ask Claude to start each one during the session:

111 127 

128```bash theme={null}

129service postgresql start

112```130```

113& Fix the flaky test in auth.spec.ts

114& Update the API documentation

115& Refactor the logger to use structured output

116```

117 

118Monitor all sessions with `/tasks`. When a session completes, you can create a PR from the web interface or [teleport](#from-web-to-terminal) the session to your terminal to continue working.

119 

120### From web to terminal

121 131 

122There are several ways to pull a web session into your terminal:132```bash theme={null}

133service redis-server start

134```

123 135 

124* **Using `/teleport`**: From within Claude Code, run `/teleport` (or `/tp`) to see an interactive picker of your web sessions. If you have uncommitted changes, you'll be prompted to stash them first.136Docker is available for running containerized services. Ask Claude to run `docker compose up` to start your project's services. Network access to pull images follows your environment's [access level](#access-levels), and the [Trusted defaults](#default-allowed-domains) include Docker Hub and other common registries.

125* **Using `--teleport`**: From the command line, run `claude --teleport` for an interactive session picker, or `claude --teleport <session-id>` to resume a specific session directly.

126* **From `/tasks`**: Run `/tasks` to see your background sessions, then press `t` to teleport into one

127* **From the web interface**: Click "Open in CLI" to copy a command you can paste into your terminal

128 137 

129When you teleport a session, Claude verifies you're in the correct repository, fetches and checks out the branch from the remote session, and loads the full conversation history into your terminal.138If your images are large or slow to pull, add `docker compose pull` or `docker compose build` to your [setup script](#setup-scripts). The pulled images are saved in the [cached environment](#environment-caching), so each new session has them on disk. The cache stores files only, not running processes, so Claude still starts the containers each session.

130 139 

131#### Requirements for teleporting140To add packages that aren't pre-installed, use a [setup script](#setup-scripts). The script's output is [cached](#environment-caching), so packages you install there are available at the start of every session without reinstalling each time. You can also ask Claude to install packages mid-session, but those installs don't carry over to other sessions.

132 141 

133Teleport checks these requirements before resuming a session. If any requirement isn't met, you'll see an error or be prompted to resolve the issue.142### Resource limits

134 143 

135| Requirement | Details |144Cloud sessions run with approximate resource ceilings that may change over time:

136| ------------------ | ---------------------------------------------------------------------------------------------------------------------- |

137| Clean git state | Your working directory must have no uncommitted changes. Teleport prompts you to stash changes if needed. |

138| Correct repository | You must run `--teleport` from a checkout of the same repository, not a fork. |

139| Branch available | The branch from the web session must have been pushed to the remote. Teleport automatically fetches and checks it out. |

140| Same account | You must be authenticated to the same Claude.ai account used in the web session. |

141 145 

142## Cloud environment146* 4 vCPUs

147* 16 GB of RAM

148* 30 GB of disk

143 149 

144### Default image150Tasks requiring significantly more memory, such as large build jobs or memory-intensive tests, may fail or be terminated. For workloads beyond these limits, use [Remote Control](/en/remote-control) to run Claude Code on your own hardware.

145 151 

146We build and maintain a universal image with common toolchains and language ecosystems pre-installed. This image includes:152### Configure your environment

147 153 

148* Popular programming languages and runtimes154Environments control [network access](#network-access), environment variables, and the [setup script](#setup-scripts) that runs before a session starts. See [Installed tools](#installed-tools) for what's available without any configuration. You can manage environments from the web interface or the terminal:

149* Common build tools and package managers

150* Testing frameworks and linters

151 155 

152#### Checking available tools156| Action | How |

157| :----------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

158| Add an environment | Select the current environment to open the selector, then select **Add environment**. The dialog includes name, network access level, environment variables, and setup script. |

159| Edit an environment | Select the settings icon to the right of the environment name. |

160| Archive an environment | Open the environment for editing and select **Archive**. Archived environments are hidden from the selector but existing sessions keep running. |

161| Set the default for `--remote` | Run `/remote-env` in your terminal. If you have a single environment, this command shows your current configuration. `/remote-env` only selects the default; add, edit, and archive environments from the web interface. |

153 162 

154To see what's pre-installed in your environment, ask Claude Code to run:163Environment variables use `.env` format with one `KEY=value` pair per line. Don't wrap values in quotes, since quotes are stored as part of the value.

155 164 

156```bash theme={null}165```text theme={null}

157check-tools166NODE_ENV=development

167LOG_LEVEL=debug

168DATABASE_URL=postgres://localhost:5432/myapp

158```169```

159 170 

160This command displays:171## Setup scripts

161 

162* Programming languages and their versions

163* Available package managers

164* Installed development tools

165 172 

166#### Language-specific setups173A setup script is a Bash script that runs when a new cloud session starts, before Claude Code launches. Use setup scripts to install dependencies, configure tools, or fetch anything the session needs that isn't pre-installed.

167 174 

168The universal image includes pre-configured environments for:175Scripts run as root on Ubuntu 24.04, so `apt install` and most language package managers work.

169 176 

170* **Python**: Python 3.x with pip, poetry, and common scientific libraries177To add a setup script, open the environment settings dialog and enter your script in the **Setup script** field.

171* **Node.js**: Latest LTS versions with npm, yarn, pnpm, and bun

172* **Ruby**: Versions 3.1.6, 3.2.6, 3.3.6 (default: 3.3.6) with gem, bundler, and rbenv for version management

173* **PHP**: Version 8.4.14

174* **Java**: OpenJDK with Maven and Gradle

175* **Go**: Latest stable version with module support

176* **Rust**: Rust toolchain with cargo

177* **C++**: GCC and Clang compilers

178 178 

179#### Databases179This example installs the `gh` CLI, which isn't pre-installed:

180 180 

181The universal image includes the following databases:181```bash theme={null}

182 182#!/bin/bash

183* **PostgreSQL**: Version 16183apt update && apt install -y gh

184* **Redis**: Version 7.0184```

185 185 

186### Environment configuration186If the script exits non-zero, the session fails to start. Append `|| true` to non-critical commands to avoid blocking the session on an intermittent install failure.

187 187 

188When you start a session in Claude Code on the web, here's what happens under the hood:188<Note>

189 Setup scripts that install packages need network access to reach registries. The default **Trusted** network access allows connections to [common package registries](#default-allowed-domains) including npm, PyPI, RubyGems, and crates.io. Scripts will fail to install packages if your environment uses **None** network access.

190</Note>

189 191 

1901. **Environment preparation**: We clone your repository and run any configured Claude hooks for initialization. The repo will be cloned with the default branch on your GitHub repo. If you would like to check out a specific branch, you can specify that in the prompt.192### Environment caching

191 193 

1922. **Network configuration**: We configure internet access for the agent. Internet access is limited by default, but you can configure the environment to have no internet or full internet access based on your needs.194The setup script runs the first time you start a session in an environment. After it completes, Anthropic snapshots the filesystem and reuses that snapshot as the starting point for later sessions. New sessions start with your dependencies, tools, and Docker images already on disk, and the setup script step is skipped. This keeps startup fast even when the script installs large toolchains or pulls container images.

193 195 

1943. **Claude Code execution**: Claude Code runs to complete your task, writing code, running tests, and checking its work. You can guide and steer Claude throughout the session via the web interface. Claude respects context you've defined in your `CLAUDE.md`.196The cache captures files, not running processes. Anything the setup script writes to disk carries over. Services or containers it starts do not, so start those per session by asking Claude or with a [SessionStart hook](#setup-scripts-vs-sessionstart-hooks).

195 197 

1964. **Outcome**: When Claude completes its work, it will push the branch to remote. You will be able to create a PR for the branch.198The setup script runs again to rebuild the cache when you change the environment's setup script or allowed network hosts, and when the cache reaches its expiry after roughly seven days. Resuming an existing session never re-runs the setup script.

197 199 

198<Note>200You don't need to enable caching or manage snapshots yourself.

199 Claude operates entirely through the terminal and CLI tools available in the environment. It uses the pre-installed tools in the universal image and any additional tools you install through hooks or dependency management.

200</Note>

201 201 

202**To add a new environment:** Select the current environment to open the environment selector, and then select "Add environment". This will open a dialog where you can specify the environment name, network access level, and any environment variables you want to set.202### Setup scripts vs. SessionStart hooks

203 203 

204**To update an existing environment:** Select the current environment, to the right of the environment name, and select the settings button. This will open a dialog where you can update the environment name, network access, and environment variables.204Use a setup script to install things the cloud needs but your laptop already has, like a language runtime or CLI tool. Use a [SessionStart hook](/en/hooks#sessionstart) for project setup that should run everywhere, cloud and local, like `npm install`.

205 205 

206**To select your default environment from the terminal:** If you have multiple environments configured, run `/remote-env` to choose which one to use when starting web sessions from your terminal with `&` or `--remote`. With a single environment, this command shows your current configuration.206Both run at the start of a session, but they belong to different places:

207 207 

208<Note>208| | Setup scripts | SessionStart hooks |

209 Environment variables must be specified as key-value pairs, in [`.env` format](https://www.dotenv.org/). For example:209| ------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |

210| Attached to | The cloud environment | Your repository |

211| Configured in | Cloud environment UI | `.claude/settings.json` in your repo |

212| Runs | Before Claude Code launches, when no [cached environment](#environment-caching) is available | After Claude Code launches, on every session including resumed |

213| Scope | Cloud environments only | Both local and cloud |

210 214 

211 ```215SessionStart hooks can also be defined in your user-level `~/.claude/settings.json` locally, but user-level settings don't carry over to cloud sessions. In the cloud, only hooks committed to the repo run.

212 API_KEY=your_api_key

213 DEBUG=true

214 ```

215</Note>

216 216 

217### Dependency management217### Install dependencies with a SessionStart hook

218 218 

219Configure automatic dependency installation using [SessionStart hooks](/en/hooks#sessionstart). This can be configured in your repository's `.claude/settings.json` file:219To install dependencies only in cloud sessions, add a SessionStart hook to your repo's `.claude/settings.json`:

220 220 

221```json theme={null}221```json theme={null}

222{222{

223 "hooks": {223 "hooks": {

224 "SessionStart": [224 "SessionStart": [

225 {225 {

226 "matcher": "startup",226 "matcher": "startup|resume",

227 "hooks": [227 "hooks": [

228 {228 {

229 "type": "command",229 "type": "command",


236}236}

237```237```

238 238 

239Create the corresponding script at `scripts/install_pkgs.sh`:239Create the script at `scripts/install_pkgs.sh` and make it executable with `chmod +x`. The `CLAUDE_CODE_REMOTE` environment variable is set to `true` in cloud sessions, so you can use it to skip local execution:

240 240 

241```bash theme={null}241```bash theme={null}

242#!/bin/bash242#!/bin/bash

243 

244if [ "$CLAUDE_CODE_REMOTE" != "true" ]; then

245 exit 0

246fi

247 

243npm install248npm install

244pip install -r requirements.txt249pip install -r requirements.txt

245exit 0250exit 0

246```251```

247 252 

248Make it executable: `chmod +x scripts/install_pkgs.sh`253SessionStart hooks have some limitations in cloud sessions:

249 254 

250#### Local vs remote execution255* **No cloud-only scoping**: hooks run in both local and cloud sessions. To skip local execution, check the `CLAUDE_CODE_REMOTE` environment variable as shown above.

256* **Requires network access**: install commands need to reach package registries. If your environment uses **None** network access, these hooks fail. The [default allowlist](#default-allowed-domains) under **Trusted** covers npm, PyPI, RubyGems, and crates.io.

257* **Proxy compatibility**: all outbound traffic passes through a [security proxy](#security-proxy). Some package managers don't work correctly with this proxy. Bun is a known example.

258* **Adds startup latency**: hooks run each time a session starts or resumes, unlike setup scripts which benefit from [environment caching](#environment-caching). Keep install scripts fast by checking whether dependencies are already present before reinstalling.

251 259 

252By default, all hooks execute both locally and in remote (web) environments. To run a hook only in one environment, check the `CLAUDE_CODE_REMOTE` environment variable in your hook script.260To persist environment variables for subsequent Bash commands, write to the file at `$CLAUDE_ENV_FILE`. See [SessionStart hooks](/en/hooks#sessionstart) for details.

253 261 

254```bash theme={null}262Replacing the base image with your own Docker image is not yet supported. Use a setup script to install what you need on top of the [provided image](#installed-tools), or run your image as a container alongside Claude with `docker compose`.

255#!/bin/bash

256 263 

257# Example: Only run in remote environments264## Network access

258if [ "$CLAUDE_CODE_REMOTE" != "true" ]; then

259 exit 0

260fi

261 265 

262npm install266Network access controls outbound connections from the cloud environment. Each environment specifies one access level, and you can extend it with custom allowed domains. The default is **Trusted**, which allows package registries and other [allowlisted domains](#default-allowed-domains).

263pip install -r requirements.txt

264```

265 267 

266#### Persisting environment variables268### Access levels

267 269 

268SessionStart hooks can persist environment variables for subsequent bash commands by writing to the file specified in the `CLAUDE_ENV_FILE` environment variable. For details, see [SessionStart hooks](/en/hooks#sessionstart) in the hooks reference.270Choose an access level when you create or edit an environment:

269 271 

270## Network access and security272| Level | Outbound connections |

273| :---------- | :------------------------------------------------------------------------------------------- |

274| **None** | No outbound network access |

275| **Trusted** | [Allowlisted domains](#default-allowed-domains) only: package registries, GitHub, cloud SDKs |

276| **Full** | Any domain |

277| **Custom** | Your own allowlist, optionally including the defaults |

271 278 

272### Network policy279GitHub operations use a [separate proxy](#github-proxy) that is independent of this setting.

273 280 

274#### GitHub proxy281### Allow specific domains

282 

283To allow domains that aren't in the Trusted list, select **Custom** in the environment's network access settings. An **Allowed domains** field appears. Enter one domain per line:

284 

285```text theme={null}

286api.example.com

287*.internal.example.com

288registry.example.com

289```

290 

291Use `*.` for wildcard subdomain matching. Check **Also include default list of common package managers** to keep the [Trusted domains](#default-allowed-domains) alongside your custom entries, or leave it unchecked to allow only what you list.

292 

293### GitHub proxy

275 294 

276For security, all GitHub operations go through a dedicated proxy service that transparently handles all git interactions. Inside the sandbox, the git client authenticates using a custom-built scoped credential. This proxy:295For security, all GitHub operations go through a dedicated proxy service that transparently handles all git interactions. Inside the sandbox, the git client authenticates using a custom-built scoped credential. This proxy:

277 296 

278* Manages GitHub authentication securely - the git client uses a scoped credential inside the sandbox, which the proxy verifies and translates to your actual GitHub authentication token297* Manages GitHub authentication securely: the git client uses a scoped credential inside the sandbox, which the proxy verifies and translates to your actual GitHub authentication token

279* Restricts git push operations to the current working branch for safety298* Restricts git push operations to the current working branch for safety

280* Enables seamless cloning, fetching, and PR operations while maintaining security boundaries299* Enables cloning, fetching, and PR operations while maintaining security boundaries

281 300 

282#### Security proxy301### Security proxy

283 302 

284Environments run behind an HTTP/HTTPS network proxy for security and abuse prevention purposes. All outbound internet traffic passes through this proxy, which provides:303Environments run behind an HTTP/HTTPS network proxy for security and abuse prevention purposes. All outbound internet traffic passes through this proxy, which provides:

285 304 


287* Rate limiting and abuse prevention306* Rate limiting and abuse prevention

288* Content filtering for enhanced security307* Content filtering for enhanced security

289 308 

290### Access levels309### Default allowed domains

291 310 

292By default, network access is limited to [allowlisted domains](#default-allowed-domains).311When using **Trusted** network access, the following domains are allowed by default. Domains marked with `*` indicate wildcard subdomain matching, so `*.gcr.io` allows any subdomain of `gcr.io`.

312 

313<AccordionGroup>

314 <Accordion title="Anthropic services">

315 * api.anthropic.com

316 * statsig.anthropic.com

317 * docs.claude.com

318 * platform.claude.com

319 * code.claude.com

320 * claude.ai

321 </Accordion>

322 

323 <Accordion title="Version control">

324 * github.com

325 * [www.github.com](http://www.github.com)

326 * api.github.com

327 * npm.pkg.github.com

328 * raw\.githubusercontent.com

329 * pkg-npm.githubusercontent.com

330 * objects.githubusercontent.com

331 * release-assets.githubusercontent.com

332 * codeload.github.com

333 * avatars.githubusercontent.com

334 * camo.githubusercontent.com

335 * gist.github.com

336 * gitlab.com

337 * [www.gitlab.com](http://www.gitlab.com)

338 * registry.gitlab.com

339 * bitbucket.org

340 * [www.bitbucket.org](http://www.bitbucket.org)

341 * api.bitbucket.org

342 </Accordion>

343 

344 <Accordion title="Container registries">

345 * registry-1.docker.io

346 * auth.docker.io

347 * index.docker.io

348 * hub.docker.com

349 * [www.docker.com](http://www.docker.com)

350 * production.cloudflare.docker.com

351 * download.docker.com

352 * gcr.io

353 * \*.gcr.io

354 * ghcr.io

355 * mcr.microsoft.com

356 * \*.data.mcr.microsoft.com

357 * public.ecr.aws

358 </Accordion>

359 

360 <Accordion title="Cloud platforms">

361 * cloud.google.com

362 * accounts.google.com

363 * gcloud.google.com

364 * \*.googleapis.com

365 * storage.googleapis.com

366 * compute.googleapis.com

367 * container.googleapis.com

368 * azure.com

369 * portal.azure.com

370 * microsoft.com

371 * [www.microsoft.com](http://www.microsoft.com)

372 * \*.microsoftonline.com

373 * packages.microsoft.com

374 * dotnet.microsoft.com

375 * dot.net

376 * visualstudio.com

377 * dev.azure.com

378 * \*.amazonaws.com

379 * \*.api.aws

380 * oracle.com

381 * [www.oracle.com](http://www.oracle.com)

382 * java.com

383 * [www.java.com](http://www.java.com)

384 * java.net

385 * [www.java.net](http://www.java.net)

386 * download.oracle.com

387 * yum.oracle.com

388 </Accordion>

389 

390 <Accordion title="JavaScript and Node package managers">

391 * registry.npmjs.org

392 * [www.npmjs.com](http://www.npmjs.com)

393 * [www.npmjs.org](http://www.npmjs.org)

394 * npmjs.com

395 * npmjs.org

396 * yarnpkg.com

397 * registry.yarnpkg.com

398 </Accordion>

399 

400 <Accordion title="Python package managers">

401 * pypi.org

402 * [www.pypi.org](http://www.pypi.org)

403 * files.pythonhosted.org

404 * pythonhosted.org

405 * test.pypi.org

406 * pypi.python.org

407 * pypa.io

408 * [www.pypa.io](http://www.pypa.io)

409 </Accordion>

410 

411 <Accordion title="Ruby package managers">

412 * rubygems.org

413 * [www.rubygems.org](http://www.rubygems.org)

414 * api.rubygems.org

415 * index.rubygems.org

416 * ruby-lang.org

417 * [www.ruby-lang.org](http://www.ruby-lang.org)

418 * rubyforge.org

419 * [www.rubyforge.org](http://www.rubyforge.org)

420 * rubyonrails.org

421 * [www.rubyonrails.org](http://www.rubyonrails.org)

422 * rvm.io

423 * get.rvm.io

424 </Accordion>

425 

426 <Accordion title="Rust package managers">

427 * crates.io

428 * [www.crates.io](http://www.crates.io)

429 * index.crates.io

430 * static.crates.io

431 * rustup.rs

432 * static.rust-lang.org

433 * [www.rust-lang.org](http://www.rust-lang.org)

434 </Accordion>

435 

436 <Accordion title="Go package managers">

437 * proxy.golang.org

438 * sum.golang.org

439 * index.golang.org

440 * golang.org

441 * [www.golang.org](http://www.golang.org)

442 * goproxy.io

443 * pkg.go.dev

444 </Accordion>

445 

446 <Accordion title="JVM package managers">

447 * maven.org

448 * repo.maven.org

449 * central.maven.org

450 * repo1.maven.org

451 * repo.maven.apache.org

452 * jcenter.bintray.com

453 * gradle.org

454 * [www.gradle.org](http://www.gradle.org)

455 * services.gradle.org

456 * plugins.gradle.org

457 * kotlinlang.org

458 * [www.kotlinlang.org](http://www.kotlinlang.org)

459 * spring.io

460 * repo.spring.io

461 </Accordion>

462 

463 <Accordion title="Other package managers">

464 * packagist.org (PHP Composer)

465 * [www.packagist.org](http://www.packagist.org)

466 * repo.packagist.org

467 * nuget.org (.NET NuGet)

468 * [www.nuget.org](http://www.nuget.org)

469 * api.nuget.org

470 * pub.dev (Dart/Flutter)

471 * api.pub.dev

472 * hex.pm (Elixir/Erlang)

473 * [www.hex.pm](http://www.hex.pm)

474 * cpan.org (Perl CPAN)

475 * [www.cpan.org](http://www.cpan.org)

476 * metacpan.org

477 * [www.metacpan.org](http://www.metacpan.org)

478 * api.metacpan.org

479 * cocoapods.org (iOS/macOS)

480 * [www.cocoapods.org](http://www.cocoapods.org)

481 * cdn.cocoapods.org

482 * haskell.org

483 * [www.haskell.org](http://www.haskell.org)

484 * hackage.haskell.org

485 * swift.org

486 * [www.swift.org](http://www.swift.org)

487 </Accordion>

488 

489 <Accordion title="Linux distributions">

490 * archive.ubuntu.com

491 * security.ubuntu.com

492 * ubuntu.com

493 * [www.ubuntu.com](http://www.ubuntu.com)

494 * \*.ubuntu.com

495 * ppa.launchpad.net

496 * launchpad.net

497 * [www.launchpad.net](http://www.launchpad.net)

498 * \*.nixos.org

499 </Accordion>

500 

501 <Accordion title="Development tools and platforms">

502 * dl.k8s.io (Kubernetes)

503 * pkgs.k8s.io

504 * k8s.io

505 * [www.k8s.io](http://www.k8s.io)

506 * releases.hashicorp.com (HashiCorp)

507 * apt.releases.hashicorp.com

508 * rpm.releases.hashicorp.com

509 * archive.releases.hashicorp.com

510 * hashicorp.com

511 * [www.hashicorp.com](http://www.hashicorp.com)

512 * repo.anaconda.com (Anaconda/Conda)

513 * conda.anaconda.org

514 * anaconda.org

515 * [www.anaconda.com](http://www.anaconda.com)

516 * anaconda.com

517 * continuum.io

518 * apache.org (Apache)

519 * [www.apache.org](http://www.apache.org)

520 * archive.apache.org

521 * downloads.apache.org

522 * eclipse.org (Eclipse)

523 * [www.eclipse.org](http://www.eclipse.org)

524 * download.eclipse.org

525 * nodejs.org (Node.js)

526 * [www.nodejs.org](http://www.nodejs.org)

527 * developer.apple.com

528 * developer.android.com

529 * pkg.stainless.com

530 * binaries.prisma.sh

531 </Accordion>

532 

533 <Accordion title="Cloud services and monitoring">

534 * statsig.com

535 * [www.statsig.com](http://www.statsig.com)

536 * api.statsig.com

537 * sentry.io

538 * \*.sentry.io

539 * downloads.sentry-cdn.com

540 * http-intake.logs.datadoghq.com

541 * \*.datadoghq.com

542 * \*.datadoghq.eu

543 * api.honeycomb.io

544 </Accordion>

545 

546 <Accordion title="Content delivery and mirrors">

547 * sourceforge.net

548 * \*.sourceforge.net

549 * packagecloud.io

550 * \*.packagecloud.io

551 * fonts.googleapis.com

552 * fonts.gstatic.com

553 </Accordion>

554 

555 <Accordion title="Schema and configuration">

556 * json-schema.org

557 * [www.json-schema.org](http://www.json-schema.org)

558 * json.schemastore.org

559 * [www.schemastore.org](http://www.schemastore.org)

560 </Accordion>

561 

562 <Accordion title="Model Context Protocol">

563 * \*.modelcontextprotocol.io

564 </Accordion>

565</AccordionGroup>

566 

567## Move tasks between web and terminal

568 

569These workflows require the [Claude Code CLI](/en/quickstart) signed in to the same claude.ai account. You can start new cloud sessions from your terminal, or pull cloud sessions into your terminal to continue locally. Cloud sessions persist even if you close your laptop, and you can monitor them from anywhere including the Claude mobile app.

293 570 

294You can configure custom network access, including disabling network access.571<Note>

572 From the CLI, session handoff is one-way: you can pull cloud sessions into your terminal with `--teleport`, but you can't push an existing terminal session to the web. The `--remote` flag creates a new cloud session for your current repository. The [Desktop app](/en/desktop#continue-in-another-surface) provides a Continue in menu that can send a local session to the web.

573</Note>

295 574 

296### Default allowed domains575### From terminal to web

576 

577Start a cloud session from the command line with the `--remote` flag:

578 

579```bash theme={null}

580claude --remote "Fix the authentication bug in src/auth/login.ts"

581```

297 582 

298When using "Limited" network access, the following domains are allowed by default:583This creates a new cloud session on claude.ai. The session clones your current directory's GitHub remote at your current branch, so push first if you have local commits, since the VM clones from GitHub rather than your machine. `--remote` works with a single repository at a time. The task runs in the cloud while you continue working locally.

299 

300#### Anthropic Services

301 

302* api.anthropic.com

303* statsig.anthropic.com

304* docs.claude.com

305* code.claude.com

306* claude.ai

307 

308#### Version Control

309 

310* github.com

311* [www.github.com](http://www.github.com)

312* api.github.com

313* npm.pkg.github.com

314* raw\.githubusercontent.com

315* pkg-npm.githubusercontent.com

316* objects.githubusercontent.com

317* codeload.github.com

318* avatars.githubusercontent.com

319* camo.githubusercontent.com

320* gist.github.com

321* gitlab.com

322* [www.gitlab.com](http://www.gitlab.com)

323* registry.gitlab.com

324* bitbucket.org

325* [www.bitbucket.org](http://www.bitbucket.org)

326* api.bitbucket.org

327 

328#### Container Registries

329 

330* registry-1.docker.io

331* auth.docker.io

332* index.docker.io

333* hub.docker.com

334* [www.docker.com](http://www.docker.com)

335* production.cloudflare.docker.com

336* download.docker.com

337* gcr.io

338* \*.gcr.io

339* ghcr.io

340* mcr.microsoft.com

341* \*.data.mcr.microsoft.com

342* public.ecr.aws

343 

344#### Cloud Platforms

345 

346* cloud.google.com

347* accounts.google.com

348* gcloud.google.com

349* \*.googleapis.com

350* storage.googleapis.com

351* compute.googleapis.com

352* container.googleapis.com

353* azure.com

354* portal.azure.com

355* microsoft.com

356* [www.microsoft.com](http://www.microsoft.com)

357* \*.microsoftonline.com

358* packages.microsoft.com

359* dotnet.microsoft.com

360* dot.net

361* visualstudio.com

362* dev.azure.com

363* \*.amazonaws.com

364* \*.api.aws

365* oracle.com

366* [www.oracle.com](http://www.oracle.com)

367* java.com

368* [www.java.com](http://www.java.com)

369* java.net

370* [www.java.net](http://www.java.net)

371* download.oracle.com

372* yum.oracle.com

373 

374#### Package Managers - JavaScript/Node

375 

376* registry.npmjs.org

377* [www.npmjs.com](http://www.npmjs.com)

378* [www.npmjs.org](http://www.npmjs.org)

379* npmjs.com

380* npmjs.org

381* yarnpkg.com

382* registry.yarnpkg.com

383 

384#### Package Managers - Python

385 

386* pypi.org

387* [www.pypi.org](http://www.pypi.org)

388* files.pythonhosted.org

389* pythonhosted.org

390* test.pypi.org

391* pypi.python.org

392* pypa.io

393* [www.pypa.io](http://www.pypa.io)

394 

395#### Package Managers - Ruby

396 

397* rubygems.org

398* [www.rubygems.org](http://www.rubygems.org)

399* api.rubygems.org

400* index.rubygems.org

401* ruby-lang.org

402* [www.ruby-lang.org](http://www.ruby-lang.org)

403* rubyforge.org

404* [www.rubyforge.org](http://www.rubyforge.org)

405* rubyonrails.org

406* [www.rubyonrails.org](http://www.rubyonrails.org)

407* rvm.io

408* get.rvm.io

409 

410#### Package Managers - Rust

411 

412* crates.io

413* [www.crates.io](http://www.crates.io)

414* index.crates.io

415* static.crates.io

416* rustup.rs

417* static.rust-lang.org

418* [www.rust-lang.org](http://www.rust-lang.org)

419 

420#### Package Managers - Go

421 

422* proxy.golang.org

423* sum.golang.org

424* index.golang.org

425* golang.org

426* [www.golang.org](http://www.golang.org)

427* goproxy.io

428* pkg.go.dev

429 

430#### Package Managers - JVM

431 

432* maven.org

433* repo.maven.org

434* central.maven.org

435* repo1.maven.org

436* jcenter.bintray.com

437* gradle.org

438* [www.gradle.org](http://www.gradle.org)

439* services.gradle.org

440* plugins.gradle.org

441* kotlin.org

442* [www.kotlin.org](http://www.kotlin.org)

443* spring.io

444* repo.spring.io

445 

446#### Package Managers - Other Languages

447 

448* packagist.org (PHP Composer)

449* [www.packagist.org](http://www.packagist.org)

450* repo.packagist.org

451* nuget.org (.NET NuGet)

452* [www.nuget.org](http://www.nuget.org)

453* api.nuget.org

454* pub.dev (Dart/Flutter)

455* api.pub.dev

456* hex.pm (Elixir/Erlang)

457* [www.hex.pm](http://www.hex.pm)

458* cpan.org (Perl CPAN)

459* [www.cpan.org](http://www.cpan.org)

460* metacpan.org

461* [www.metacpan.org](http://www.metacpan.org)

462* api.metacpan.org

463* cocoapods.org (iOS/macOS)

464* [www.cocoapods.org](http://www.cocoapods.org)

465* cdn.cocoapods.org

466* haskell.org

467* [www.haskell.org](http://www.haskell.org)

468* hackage.haskell.org

469* swift.org

470* [www.swift.org](http://www.swift.org)

471 

472#### Linux Distributions

473 

474* archive.ubuntu.com

475* security.ubuntu.com

476* ubuntu.com

477* [www.ubuntu.com](http://www.ubuntu.com)

478* \*.ubuntu.com

479* ppa.launchpad.net

480* launchpad.net

481* [www.launchpad.net](http://www.launchpad.net)

482 

483#### Development Tools & Platforms

484 

485* dl.k8s.io (Kubernetes)

486* pkgs.k8s.io

487* k8s.io

488* [www.k8s.io](http://www.k8s.io)

489* releases.hashicorp.com (HashiCorp)

490* apt.releases.hashicorp.com

491* rpm.releases.hashicorp.com

492* archive.releases.hashicorp.com

493* hashicorp.com

494* [www.hashicorp.com](http://www.hashicorp.com)

495* repo.anaconda.com (Anaconda/Conda)

496* conda.anaconda.org

497* anaconda.org

498* [www.anaconda.com](http://www.anaconda.com)

499* anaconda.com

500* continuum.io

501* apache.org (Apache)

502* [www.apache.org](http://www.apache.org)

503* archive.apache.org

504* downloads.apache.org

505* eclipse.org (Eclipse)

506* [www.eclipse.org](http://www.eclipse.org)

507* download.eclipse.org

508* nodejs.org (Node.js)

509* [www.nodejs.org](http://www.nodejs.org)

510 

511#### Cloud Services & Monitoring

512 

513* statsig.com

514* [www.statsig.com](http://www.statsig.com)

515* api.statsig.com

516* sentry.io

517* \*.sentry.io

518* http-intake.logs.datadoghq.com

519* \*.datadoghq.com

520* \*.datadoghq.eu

521 

522#### Content Delivery & Mirrors

523 

524* sourceforge.net

525* \*.sourceforge.net

526* packagecloud.io

527* \*.packagecloud.io

528 

529#### Schema & Configuration

530 

531* json-schema.org

532* [www.json-schema.org](http://www.json-schema.org)

533* json.schemastore.org

534* [www.schemastore.org](http://www.schemastore.org)

535 

536#### Model Context Protocol

537 

538* \*.modelcontextprotocol.io

539 584 

540<Note>585<Note>

541 Domains marked with `*` indicate wildcard subdomain matching. For example, `*.gcr.io` allows access to any subdomain of `gcr.io`.586 `--remote` creates cloud sessions. `--remote-control` is unrelated: it exposes a local CLI session for monitoring from the web. See [Remote Control](/en/remote-control).

542</Note>587</Note>

543 588 

544### Security best practices for customized network access589Use `/tasks` in the Claude Code CLI to check progress, or open the session on claude.ai or the Claude mobile app to interact directly. From there you can steer Claude, provide feedback, or answer questions just like any other conversation.

545 590 

5461. **Principle of least privilege**: Only enable the minimum network access required591#### Tips for cloud tasks

5472. **Audit regularly**: Review allowed domains periodically

5483. **Use HTTPS**: Always prefer HTTPS endpoints over HTTP

549 592 

550## Security and isolation593**Plan locally, execute remotely**: for complex tasks, start Claude in plan mode to collaborate on the approach, then send work to the cloud:

594 

595```bash theme={null}

596claude --permission-mode plan

597```

551 598 

552Claude Code on the web provides strong security guarantees:599In plan mode, Claude reads files, runs commands to explore, and proposes a plan without editing source code. Once you're satisfied, save the plan to the repo, commit, and push so the cloud VM can clone it. Then start a cloud session for autonomous execution:

553 600 

554* **Isolated virtual machines**: Each session runs in an isolated, Anthropic-managed VM601```bash theme={null}

555* **Network access controls**: Network access is limited by default, and can be disabled602claude --remote "Execute the migration plan in docs/migration-plan.md"

603```

604 

605This pattern gives you control over the strategy while letting Claude execute autonomously in the cloud.

606 

607**Plan in the cloud with ultraplan**: to draft and review the plan itself in a web session, use [ultraplan](/en/ultraplan). Claude generates the plan on Claude Code on the web while you keep working, then you comment on sections in your browser and choose to execute remotely or send the plan back to your terminal.

608 

609**Run tasks in parallel**: each `--remote` command creates its own cloud session that runs independently. You can start multiple tasks and they'll all run simultaneously in separate sessions:

610 

611```bash theme={null}

612claude --remote "Fix the flaky test in auth.spec.ts"

613claude --remote "Update the API documentation"

614claude --remote "Refactor the logger to use structured output"

615```

616 

617Monitor all sessions with `/tasks` in the Claude Code CLI. When a session completes, you can create a PR from the web interface or [teleport](#from-web-to-terminal) the session to your terminal to continue working.

618 

619#### Send local repositories without GitHub

620 

621When you run `claude --remote` from a repository that isn't connected to GitHub, Claude Code bundles your local repository and uploads it directly to the cloud session. The bundle includes your full repository history across all branches, plus any uncommitted changes to tracked files.

622 

623This fallback activates automatically when GitHub access isn't available. To force it even when GitHub is connected, set `CCR_FORCE_BUNDLE=1`:

624 

625```bash theme={null}

626CCR_FORCE_BUNDLE=1 claude --remote "Run the test suite and fix any failures"

627```

628 

629Bundled repositories must meet these limits:

630 

631* The directory must be a git repository with at least one commit

632* The bundled repository must be under 100 MB. Larger repositories fall back to bundling only the current branch, then to a single squashed snapshot of the working tree, and fail only if the snapshot is still too large

633* Untracked files are not included; run `git add` on files you want the cloud session to see

634* Sessions created from a bundle can't push back to a remote unless you also have [GitHub authentication](#github-authentication-options) configured

635 

636### From web to terminal

637 

638Pull a cloud session into your terminal using any of these:

639 

640* **Using `--teleport`**: from the command line, run `claude --teleport` for an interactive session picker, or `claude --teleport <session-id>` to resume a specific session directly. If you have uncommitted changes, you'll be prompted to stash them first.

641* **Using `/teleport`**: inside an existing CLI session, run `/teleport` (or `/tp`) to open the same session picker without restarting Claude Code.

642* **From `/tasks`**: run `/tasks` to see your background sessions, then press `t` to teleport into one

643* **From the web interface**: select **Open in CLI** to copy a command you can paste into your terminal

644 

645When you teleport a session, Claude verifies you're in the correct repository, fetches and checks out the branch from the cloud session, and loads the full conversation history into your terminal.

646 

647`--teleport` is distinct from `--resume`. `--resume` reopens a conversation from this machine's local history and doesn't list cloud sessions; `--teleport` pulls a cloud session and its branch.

648 

649#### Teleport requirements

650 

651Teleport checks these requirements before resuming a session. If any requirement isn't met, you'll see an error or be prompted to resolve the issue.

652 

653| Requirement | Details |

654| ------------------ | ------------------------------------------------------------------------------------------------------------------------ |

655| Clean git state | Your working directory must have no uncommitted changes. Teleport prompts you to stash changes if needed. |

656| Correct repository | You must run `--teleport` from a checkout of the same repository, not a fork. |

657| Branch available | The branch from the cloud session must have been pushed to the remote. Teleport automatically fetches and checks it out. |

658| Same account | You must be authenticated to the same claude.ai account used in the cloud session. |

659 

660#### `--teleport` is unavailable

661 

662Teleport requires claude.ai subscription authentication. If you're authenticated via API key, Bedrock, Vertex AI, or Microsoft Foundry, run `/login` to sign in with your claude.ai account instead. If you're already signed in via claude.ai and `--teleport` is still unavailable, your organization may have disabled cloud sessions.

663 

664## Work with sessions

665 

666Sessions appear in the sidebar at claude.ai/code. From there you can review changes, share with teammates, archive finished work, or delete sessions permanently.

667 

668### Manage context

669 

670Cloud sessions support [built-in commands](/en/commands) that produce text output. Commands that open an interactive terminal picker, like `/model` or `/config`, are not available.

671 

672For context management specifically:

673 

674| Command | Works in cloud sessions | Notes |

675| :--------- | :---------------------- | :----------------------------------------------------------------------------------------------------------------------- |

676| `/compact` | Yes | Summarizes the conversation to free up context. Accepts optional focus instructions like `/compact keep the test output` |

677| `/context` | Yes | Shows what's currently in the context window |

678| `/clear` | No | Start a new session from the sidebar instead |

679 

680Auto-compaction runs automatically when the context window approaches capacity, the same as in the CLI. To trigger it earlier, set [`CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`](/en/env-vars) in your [environment variables](#configure-your-environment). For example, `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=70` compacts at 70% capacity instead of the default \~95%. To change the effective window size for compaction calculations, use [`CLAUDE_CODE_AUTO_COMPACT_WINDOW`](/en/env-vars).

681 

682[Subagents](/en/sub-agents) work the same way they do locally. Claude can spawn them with the Task tool to offload research or parallel work into a separate context window, keeping the main conversation lighter. Subagents defined in your repo's `.claude/agents/` are picked up automatically. [Agent teams](/en/agent-teams) are off by default but can be enabled by adding `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` to your [environment variables](#configure-your-environment).

683 

684### Review changes

685 

686Each session shows a diff indicator with lines added and removed, like `+42 -18`. Select it to open the diff view, leave inline comments on specific lines, and send them to Claude with your next message. See [Review and iterate](/en/web-quickstart#review-and-iterate) for the full walkthrough including PR creation. To have Claude monitor the PR for CI failures and review comments automatically, see [Auto-fix pull requests](#auto-fix-pull-requests).

687 

688### Share sessions

689 

690To share a session, toggle its visibility according to the account types below. After that, share the session link as-is. Recipients see the latest state when they open the link, but their view doesn't update in real time.

691 

692#### Share from an Enterprise or Team account

693 

694For Enterprise and Team accounts, the two visibility options are **Private** and **Team**. Team visibility makes the session visible to other members of your claude.ai organization. Repository access verification is enabled by default, based on the GitHub account connected to the recipient's account. Your account's display name is visible to all recipients with access. [Claude in Slack](/en/slack) sessions are automatically shared with Team visibility.

695 

696#### Share from a Max or Pro account

697 

698For Max and Pro accounts, the two visibility options are **Private** and **Public**. Public visibility makes the session visible to any user logged into claude.ai.

699 

700Check your session for sensitive content before sharing. Sessions may contain code and credentials from private GitHub repositories. Repository access verification is not enabled by default.

701 

702To require recipients to have repository access, or to hide your name from shared sessions, go to Settings > Claude Code > Sharing settings.

703 

704### Archive sessions

705 

706You can archive sessions to keep your session list organized. Archived sessions are hidden from the default session list but can be viewed by filtering for archived sessions.

707 

708To archive a session, hover over the session in the sidebar and select the archive icon.

709 

710### Delete sessions

711 

712Deleting a session permanently removes the session and its data. This action cannot be undone. You can delete a session in two ways:

713 

714* **From the sidebar**: filter for archived sessions, then hover over the session you want to delete and select the delete icon

715* **From the session menu**: open a session, select the dropdown next to the session title, and select **Delete**

716 

717You will be asked to confirm before a session is deleted.

718 

719## Auto-fix pull requests

720 

721Claude can watch a pull request and automatically respond to CI failures and review comments. Claude subscribes to GitHub activity on the PR, and when a check fails or a reviewer leaves a comment, Claude investigates and pushes a fix if one is clear.

556 722 

557<Note>723<Note>

558 When running with network access disabled, Claude Code is allowed to communicate with the Anthropic API which may still allow data to exit the isolated Claude Code VM.724 Auto-fix requires the Claude GitHub App to be installed on your repository. If you haven't already, install it from the [GitHub App page](https://github.com/apps/claude) or when prompted during [setup](/en/web-quickstart#connect-github-and-create-an-environment).

559</Note>725</Note>

560 726 

561* **Credential protection**: Sensitive credentials (such as git credentials or signing keys) are never inside the sandbox with Claude Code. Authentication is handled through a secure proxy using scoped credentials727There are a few ways to turn on auto-fix depending on where the PR came from and what device you're using:

562* **Secure analysis**: Code is analyzed and modified within isolated VMs before creating PRs

563 728 

564## Pricing and rate limits729* **PRs created in Claude Code on the web**: open the CI status bar and select **Auto-fix**

730* **From your terminal**: run [`/autofix-pr`](/en/commands) while on the PR's branch. Claude Code detects the open PR with `gh`, spawns a web session, and turns on auto-fix in one step

731* **From the mobile app**: tell Claude to auto-fix the PR, for example "watch this PR and fix any CI failures or review comments"

732* **Any existing PR**: paste the PR URL into a session and tell Claude to auto-fix it

565 733 

566Claude Code on the web shares rate limits with all other Claude and Claude Code usage within your account. Running multiple tasks in parallel will consume more rate limits proportionately.734### How Claude responds to PR activity

567 735 

568## Limitations736When auto-fix is active, Claude receives GitHub events for the PR including new review comments and CI check failures. For each event, Claude investigates and decides how to proceed:

569 737 

570* **Repository authentication**: You can only move sessions from web to local when you are authenticated to the same account738* **Clear fixes**: if Claude is confident in a fix and it doesn't conflict with earlier instructions, Claude makes the change, pushes it, and explains what was done in the session

571* **Platform restrictions**: Claude Code on the web only works with code hosted in GitHub. GitLab and other non-GitHub repositories cannot be used with cloud sessions739* **Ambiguous requests**: if a reviewer's comment could be interpreted multiple ways or involves something architecturally significant, Claude asks you before acting

740* **Duplicate or no-action events**: if an event is a duplicate or requires no change, Claude notes it in the session and moves on

741 

742Claude may reply to review comment threads on GitHub as part of resolving them. These replies are posted using your GitHub account, so they appear under your username, but each reply is labeled as coming from Claude Code so reviewers know it was written by the agent and not by you directly.

743 

744<Warning>

745 If your repository uses comment-triggered automation such as Atlantis, Terraform Cloud, or custom GitHub Actions that run on `issue_comment` events, be aware that Claude can reply on your behalf, which can trigger those workflows. Review your repository's automation before enabling auto-fix, and consider disabling auto-fix for repositories where a PR comment can deploy infrastructure or run privileged operations.

746</Warning>

747 

748## Security and isolation

749 

750Each cloud session is separated from your machine and from other sessions through several layers:

751 

752* **Isolated virtual machines**: each session runs in an isolated, Anthropic-managed VM

753* **Network access controls**: network access is limited by default, and can be disabled. When running with network access disabled, Claude Code can still communicate with the Anthropic API, which may allow data to exit the VM.

754* **Credential protection**: sensitive credentials such as git credentials or signing keys are never inside the sandbox with Claude Code. Authentication is handled through a secure proxy using scoped credentials.

755* **Secure analysis**: code is analyzed and modified within isolated VMs before creating PRs

756 

757## Troubleshooting

758 

759For runtime API errors that appear in the conversation such as `API Error: 500`, `529 Overloaded`, `429`, or `Prompt is too long`, see the [Error reference](/en/errors). Those errors and their fixes are shared with the CLI and Desktop app. The sections below cover issues specific to cloud sessions.

760 

761### Session creation failed

762 

763If a new session fails to start with `Session creation failed` or stalls at provisioning, Claude Code could not allocate a cloud environment.

764 

765* Check [status.claude.com](https://status.claude.com) for cloud session incidents

766* Retry after a minute, as capacity is provisioned on demand

767* Confirm your repository is reachable. Private repositories require either the GitHub App installed with access to that repository, or a `gh` token synced via `/web-setup`. See [GitHub authentication options](#github-authentication-options).

768 

769### Remote Control session expired or access denied

770 

771`--teleport` connects through the same Remote Control session infrastructure that cloud sessions use, so authentication and session-expiry errors surface with Remote Control wording. You may see `Remote Control session has expired` or `Access denied`. The connection token is short-lived and scoped to your account.

772 

773* Run `/login` locally to refresh your credentials, then reconnect

774* Confirm you are signed in to the same account that owns the session

775* If you see `Remote Control may not be available for this organization`, your admin has not enabled remote sessions for your plan

776 

777### Environment expired

778 

779Cloud sessions stop after a period of inactivity and the underlying environment is reclaimed. From a local terminal, this surfaces as `Could not resume session ... its environment has expired. Creating a fresh session instead.` On the web, the session is marked expired in the session list.

780 

781Reopen the session from [claude.ai/code](https://claude.ai/code) to provision a fresh environment with your conversation history restored.

782 

783## Limitations

572 784 

573## Best practices785Before relying on cloud sessions for a workflow, account for these constraints:

574 786 

5751. **Use Claude Code hooks**: Configure [SessionStart hooks](/en/hooks#sessionstart) to automate environment setup and dependency installation.787* **Rate limits**: Claude Code on the web shares rate limits with all other Claude and Claude Code usage within your account. Running multiple tasks in parallel consumes more rate limits proportionately. There is no separate compute charge for the cloud VM.

5762. **Document requirements**: Clearly specify dependencies and commands in your `CLAUDE.md` file. If you have an `AGENTS.md` file, you can source it in your `CLAUDE.md` using `@AGENTS.md` to maintain a single source of truth.788* **Repository authentication**: you can only move sessions from web to local when you are authenticated to the same account

789* **Platform restrictions**: repository cloning and pull request creation require GitHub. Self-hosted [GitHub Enterprise Server](/en/github-enterprise-server) instances are supported for Team and Enterprise plans. GitLab, Bitbucket, and other non-GitHub repositories can be sent to cloud sessions as a [local bundle](#send-local-repositories-without-github), but the session can't push results back to the remote

577 790 

578## Related resources791## Related resources

579 792 

580* [Hooks configuration](/en/hooks)793* [Ultraplan](/en/ultraplan): draft a plan in a cloud session and review it in your browser

581* [Settings reference](/en/settings)794* [Ultrareview](/en/ultrareview): run a deep multi-agent code review in a cloud sandbox

582* [Security](/en/security)795* [Routines](/en/routines): automate work on a schedule, via API call, or in response to GitHub events

583* [Data usage](/en/data-usage)796* [Hooks configuration](/en/hooks): run scripts at session lifecycle events

797* [Settings reference](/en/settings): all configuration options

798* [Security](/en/security): isolation guarantees and data handling

799* [Data usage](/en/data-usage): what Anthropic retains from cloud sessions

claude-directory.md +149 −0 added

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# Explore the .claude directory

6 

7> Where Claude Code reads CLAUDE.md, settings.json, hooks, skills, commands, subagents, rules, and auto memory. Explore the .claude directory in your project and ~/.claude in your home directory.

8 

9 

10Claude Code reads instructions, settings, skills, subagents, and memory from your project directory and from `~/.claude` in your home directory. Commit project files to git to share them with your team; files in `~/.claude` are personal configuration that applies across all your projects.

11 

12On Windows, `~/.claude` resolves to `%USERPROFILE%\.claude`. If you set [`CLAUDE_CONFIG_DIR`](/en/env-vars), every `~/.claude` path on this page lives under that directory instead.

13 

14Most users only edit `CLAUDE.md` and `settings.json`. The rest of the directory is optional: add skills, rules, or subagents as you need them.

15 

16## Explore the directory

17 

18Click files in the tree to see what each one does, when it loads, and an example.

19 

20<ClaudeExplorer />

21 

22## What's not shown

23 

24The explorer covers files you author and edit. A few related files live elsewhere:

25 

26| File | Location | Purpose |

27| ----------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

28| `managed-settings.json` | System-level, varies by OS | Enterprise-enforced settings that you can't override. See [server-managed settings](/en/server-managed-settings). |

29| `CLAUDE.local.md` | Project root | Your private preferences for this project, loaded alongside CLAUDE.md. Create it manually and add it to `.gitignore`. |

30| Installed plugins | `~/.claude/plugins` | Cloned marketplaces, installed plugin versions, and per-plugin data, managed by `claude plugin` commands. Orphaned versions are deleted 7 days after a plugin update or uninstall. See [plugin caching](/en/plugins-reference#plugin-caching-and-file-resolution). |

31 

32`~/.claude` also holds data Claude Code writes as you work: transcripts, prompt history, file snapshots, caches, and logs. See [application data](#application-data) below.

33 

34## Choose the right file

35 

36Different kinds of customization live in different files. Use this table to find where a change belongs.

37 

38| You want to | Edit | Scope | Reference |

39| :------------------------------------------------- | :--------------------------------------- | :---------------- | :------------------------------------------------- |

40| Give Claude project context and conventions | `CLAUDE.md` | project or global | [Memory](/en/memory) |

41| Allow or block specific tool calls | `settings.json` `permissions` or `hooks` | project or global | [Permissions](/en/permissions), [Hooks](/en/hooks) |

42| Run a script before or after tool calls | `settings.json` `hooks` | project or global | [Hooks](/en/hooks) |

43| Set environment variables for the session | `settings.json` `env` | project or global | [Settings](/en/settings#available-settings) |

44| Keep personal overrides out of git | `settings.local.json` | project only | [Settings scopes](/en/settings#settings-files) |

45| Add a prompt or capability you invoke with `/name` | `skills/<name>/SKILL.md` | project or global | [Skills](/en/skills) |

46| Define a specialized subagent with its own tools | `agents/*.md` | project or global | [Subagents](/en/sub-agents) |

47| Connect external tools over MCP | `.mcp.json` | project only | [MCP](/en/mcp) |

48| Change how Claude formats responses | `output-styles/*.md` | project or global | [Output styles](/en/output-styles) |

49 

50## File reference

51 

52This table lists every file the explorer covers. Project-scope files live in your repo under `.claude/` (or at the root for `CLAUDE.md`, `.mcp.json`, and `.worktreeinclude`). Global-scope files live in `~/.claude/` and apply across all projects.

53 

54<Note>

55 Several things can override what you put in these files:

56 

57 * [Managed settings](/en/server-managed-settings) deployed by your organization take precedence over everything

58 * CLI flags like `--permission-mode` or `--settings` override `settings.json` for that session

59 * Some environment variables take precedence over their equivalent setting, but this varies: check the [environment variables reference](/en/env-vars) for each one

60 

61 See [settings precedence](/en/settings#settings-precedence) for the full order.

62</Note>

63 

64Click a filename to open that node in the explorer above.

65 

66| File | Scope | Commit | What it does | Reference |

67| --------------------------------------------------- | ------------------ | ------ | ----------------------------------------------------- | -------------------------------------------------------------------- |

68| [`CLAUDE.md`](#ce-claude-md) | Project and global | ✓ | Instructions loaded every session | [Memory](/en/memory) |

69| [`rules/*.md`](#ce-rules) | Project and global | ✓ | Topic-scoped instructions, optionally path-gated | [Rules](/en/memory#organize-rules-with-claude/rules/) |

70| [`settings.json`](#ce-settings-json) | Project and global | ✓ | Permissions, hooks, env vars, model defaults | [Settings](/en/settings) |

71| [`settings.local.json`](#ce-settings-local-json) | Project only | | Your personal overrides, auto-gitignored | [Settings scopes](/en/settings#settings-files) |

72| [`.mcp.json`](#ce-mcp-json) | Project only | ✓ | Team-shared MCP servers | [MCP scopes](/en/mcp#mcp-installation-scopes) |

73| [`.worktreeinclude`](#ce-worktreeinclude) | Project only | ✓ | Gitignored files to copy into new worktrees | [Worktrees](/en/common-workflows#copy-gitignored-files-to-worktrees) |

74| [`skills/<name>/SKILL.md`](#ce-skills) | Project and global | ✓ | Reusable prompts invoked with `/name` or auto-invoked | [Skills](/en/skills) |

75| [`commands/*.md`](#ce-commands) | Project and global | ✓ | Single-file prompts; same mechanism as skills | [Skills](/en/skills) |

76| [`output-styles/*.md`](#ce-output-styles) | Project and global | ✓ | Custom system-prompt sections | [Output styles](/en/output-styles) |

77| [`agents/*.md`](#ce-agents) | Project and global | ✓ | Subagent definitions with their own prompt and tools | [Subagents](/en/sub-agents) |

78| [`agent-memory/<name>/`](#ce-agent-memory) | Project and global | ✓ | Persistent memory for subagents | [Persistent memory](/en/sub-agents#enable-persistent-memory) |

79| [`~/.claude.json`](#ce-claude-json) | Global only | | App state, OAuth, UI toggles, personal MCP servers | [Global config](/en/settings#global-config-settings) |

80| [`projects/<project>/memory/`](#ce-global-projects) | Global only | | Auto memory: Claude's notes to itself across sessions | [Auto memory](/en/memory#auto-memory) |

81| [`keybindings.json`](#ce-keybindings) | Global only | | Custom keyboard shortcuts | [Keybindings](/en/keybindings) |

82| [`themes/*.json`](#ce-themes) | Global only | | Custom color themes | [Custom themes](/en/terminal-config#create-a-custom-theme) |

83 

84## Troubleshoot configuration

85 

86If a setting, hook, or file isn't taking effect, see [Debug your configuration](/en/debug-your-config) for the inspection commands and a symptom-first lookup table.

87 

88## Application data

89 

90Beyond the config you author, `~/.claude` holds data Claude Code writes during sessions. These files are plaintext. Anything that passes through a tool lands in a transcript on disk: file contents, command output, pasted text.

91 

92### Cleaned up automatically

93 

94Files in the paths below are deleted on startup once they're older than [`cleanupPeriodDays`](/en/settings#available-settings). The default is 30 days.

95 

96| Path under `~/.claude/` | Contents |

97| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |

98| `projects/<project>/<session>.jsonl` | Full conversation transcript: every message, tool call, and tool result |

99| `projects/<project>/<session>/tool-results/` | Large tool outputs spilled to separate files |

100| `file-history/<session>/` | Pre-edit snapshots of files Claude changed, used for [checkpoint restore](/en/checkpointing) |

101| `plans/` | Plan files written during [plan mode](/en/permission-modes#analyze-before-you-edit-with-plan-mode) |

102| `debug/` | Per-session debug logs, written only when you start with `--debug` or run `/debug` |

103| `paste-cache/`, `image-cache/` | Contents of large pastes and attached images |

104| `session-env/` | Per-session environment metadata |

105| `tasks/` | Per-session task lists written by the task tools |

106| `shell-snapshots/` | Captured shell environment used by the Bash tool. Removed on clean exit. The sweep clears any left after a crash. |

107| `backups/` | Timestamped copies of `~/.claude.json` taken before config migrations |

108 

109### Kept until you delete them

110 

111The following paths are not covered by automatic cleanup and persist indefinitely.

112 

113| Path under `~/.claude/` | Contents |

114| ----------------------- | ------------------------------------------------------------------------------------- |

115| `history.jsonl` | Every prompt you've typed, with timestamp and project path. Used for up-arrow recall. |

116| `stats-cache.json` | Aggregated token and cost counts shown by `/usage` |

117| `todos/` | Legacy per-session task lists. No longer written by current versions; safe to delete. |

118 

119Other small cache and lock files appear depending on which features you use and are safe to delete.

120 

121### Plaintext storage

122 

123Transcripts and history are not encrypted at rest. OS file permissions are the only protection. If a tool reads a `.env` file or a command prints a credential, that value is written to `projects/<project>/<session>.jsonl`. To reduce exposure:

124 

125* Lower `cleanupPeriodDays` to shorten how long transcripts are kept

126* Set the [`CLAUDE_CODE_SKIP_PROMPT_HISTORY`](/en/env-vars) environment variable to skip writing transcripts and prompt history in any mode. In non-interactive mode, you can instead pass `--no-session-persistence` alongside `-p`, or set `persistSession: false` in the Agent SDK.

127* Use [permission rules](/en/permissions) to deny reads of credential files

128 

129### Clear local data

130 

131You can delete any of the application-data paths above at any time. New sessions are unaffected. The table below shows what you lose for past sessions.

132 

133| Delete | You lose |

134| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |

135| `~/.claude/projects/` | Resume, continue, and rewind for past sessions |

136| `~/.claude/history.jsonl` | Up-arrow prompt recall |

137| `~/.claude/file-history/` | Checkpoint restore for past sessions |

138| `~/.claude/stats-cache.json` | Historical totals shown by `/usage` |

139| `~/.claude/debug/`, `~/.claude/plans/`, `~/.claude/paste-cache/`, `~/.claude/image-cache/`, `~/.claude/session-env/`, `~/.claude/tasks/`, `~/.claude/shell-snapshots/`, `~/.claude/backups/` | Nothing user-facing |

140| `~/.claude/todos/` | Nothing. Legacy directory not written by current versions. |

141 

142Don't delete `~/.claude.json`, `~/.claude/settings.json`, or `~/.claude/plugins/`: those hold your auth, preferences, and installed plugins.

143 

144## Related resources

145 

146* [Manage Claude's memory](/en/memory): write and organize CLAUDE.md, rules, and auto memory

147* [Configure settings](/en/settings): set permissions, hooks, environment variables, and model defaults

148* [Create skills](/en/skills): build reusable prompts and workflows

149* [Configure subagents](/en/sub-agents): define specialized agents with their own context

cli-reference.md +64 −93

Details

8 8 

9## CLI commands9## CLI commands

10 10 

11You can start sessions, pipe content, resume conversations, and manage updates with these commands:

12 

11| Command | Description | Example |13| Command | Description | Example |

12| :------------------------------ | :----------------------------------------------------- | :------------------------------------------------ |14| :------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------- |

13| `claude` | Start interactive REPL | `claude` |15| `claude` | Start interactive session | `claude` |

14| `claude "query"` | Start REPL with initial prompt | `claude "explain this project"` |16| `claude "query"` | Start interactive session with initial prompt | `claude "explain this project"` |

15| `claude -p "query"` | Query via SDK, then exit | `claude -p "explain this function"` |17| `claude -p "query"` | Query via SDK, then exit | `claude -p "explain this function"` |

16| `cat file \| claude -p "query"` | Process piped content | `cat logs.txt \| claude -p "explain"` |18| `cat file \| claude -p "query"` | Process piped content | `cat logs.txt \| claude -p "explain"` |

17| `claude -c` | Continue most recent conversation in current directory | `claude -c` |19| `claude -c` | Continue most recent conversation in current directory | `claude -c` |

18| `claude -c -p "query"` | Continue via SDK | `claude -c -p "Check for type errors"` |20| `claude -c -p "query"` | Continue via SDK | `claude -c -p "Check for type errors"` |

19| `claude -r "<session>" "query"` | Resume session by ID or name | `claude -r "auth-refactor" "Finish this PR"` |21| `claude -r "<session>" "query"` | Resume session by ID or name | `claude -r "auth-refactor" "Finish this PR"` |

20| `claude update` | Update to latest version | `claude update` |22| `claude update` | Update to latest version | `claude update` |

23| `claude install [version]` | Install or reinstall the native binary. Accepts a version like `2.1.118`, or `stable` or `latest`. See [Install a specific version](/en/setup#install-a-specific-version) | `claude install stable` |

24| `claude auth login` | Sign in to your Anthropic account. Use `--email` to pre-fill your email address, `--sso` to force SSO authentication, and `--console` to sign in with Anthropic Console for API usage billing instead of a Claude subscription | `claude auth login --console` |

25| `claude auth logout` | Log out from your Anthropic account | `claude auth logout` |

26| `claude auth status` | Show authentication status as JSON. Use `--text` for human-readable output. Exits with code 0 if logged in, 1 if not | `claude auth status` |

27| `claude agents` | List all configured [subagents](/en/sub-agents), grouped by source | `claude agents` |

28| `claude auto-mode defaults` | Print the built-in [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) classifier rules as JSON. Use `claude auto-mode config` to see your effective config with settings applied | `claude auto-mode defaults > rules.json` |

21| `claude mcp` | Configure Model Context Protocol (MCP) servers | See the [Claude Code MCP documentation](/en/mcp). |29| `claude mcp` | Configure Model Context Protocol (MCP) servers | See the [Claude Code MCP documentation](/en/mcp). |

30| `claude plugin` | Manage Claude Code [plugins](/en/plugins). Alias: `claude plugins`. See [plugin reference](/en/plugins-reference#cli-commands-reference) for subcommands | `claude plugin install code-review@claude-plugins-official` |

31| `claude remote-control` | Start a [Remote Control](/en/remote-control) server to control Claude Code from Claude.ai or the Claude app. Runs in server mode (no local interactive session). See [Server mode flags](/en/remote-control#start-a-remote-control-session) | `claude remote-control --name "My Project"` |

32| `claude setup-token` | Generate a long-lived OAuth token for CI and scripts. Prints the token to the terminal without saving it. Requires a Claude subscription. See [Generate a long-lived token](/en/authentication#generate-a-long-lived-token) | `claude setup-token` |

33 

34If you mistype a subcommand, Claude Code suggests the closest match and exits without starting a session. For example, `claude udpate` prints `Did you mean claude update?`.

22 35 

23## CLI flags36## CLI flags

24 37 

25Customize Claude Code's behavior with these command-line flags:38Customize Claude Code's behavior with these command-line flags. `claude --help` does not list every flag, so a flag's absence from `--help` does not mean it is unavailable.

26 39 

27| Flag | Description | Example |40| Flag | Description | Example |

28| :------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |41| :---------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |

29| `--add-dir` | Add additional working directories for Claude to access (validates each path exists as a directory) | `claude --add-dir ../apps ../lib` |42| `--add-dir` | Add additional working directories for Claude to read and edit files. Grants file access; most `.claude/` configuration is [not discovered](/en/permissions#additional-directories-grant-file-access-not-configuration) from these directories. Validates each path exists as a directory | `claude --add-dir ../apps ../lib` |

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

31| `--agents` | Define custom [subagents](/en/sub-agents) dynamically via JSON (see below for format) | `claude --agents '{"reviewer":{"description":"Reviews code","prompt":"You are a code reviewer"}}'` |44| `--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"}}'` |

32| `--allow-dangerously-skip-permissions` | Enable permission bypassing as an option without immediately activating it. Allows composing with `--permission-mode` (use with caution) | `claude --permission-mode plan --allow-dangerously-skip-permissions` |45| `--allow-dangerously-skip-permissions` | Add `bypassPermissions` to the `Shift+Tab` mode cycle without starting in it. Lets you begin in a different mode like `plan` and switch to `bypassPermissions` later. See [permission modes](/en/permission-modes#skip-all-checks-with-bypasspermissions-mode) | `claude --permission-mode plan --allow-dangerously-skip-permissions` |

33| `--allowedTools` | Tools that execute without prompting for permission. See [permission rule syntax](/en/settings#permission-rule-syntax) for pattern matching. To restrict which tools are available, use `--tools` instead | `"Bash(git log *)" "Bash(git diff *)" "Read"` |46| `--allowedTools` | Tools that execute without prompting for permission. See [permission rule syntax](/en/settings#permission-rule-syntax) for pattern matching. To restrict which tools are available, use `--tools` instead | `"Bash(git log *)" "Bash(git diff *)" "Read"` |

34| `--append-system-prompt` | Append custom text to the end of the default system prompt (works in both interactive and print modes) | `claude --append-system-prompt "Always use TypeScript"` |47| `--append-system-prompt` | Append custom text to the end of the default system prompt | `claude --append-system-prompt "Always use TypeScript"` |

35| `--append-system-prompt-file` | Load additional system prompt text from a file and append to the default prompt (print mode only) | `claude -p --append-system-prompt-file ./extra-rules.txt "query"` |48| `--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` |

49| `--bare` | Minimal mode: skip auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md so scripted calls start faster. Claude has access to Bash, file read, and file edit tools. Sets [`CLAUDE_CODE_SIMPLE`](/en/env-vars). See [bare mode](/en/headless#start-faster-with-bare-mode) | `claude --bare -p "query"` |

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

51| `--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` |

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

38| `--continue`, `-c` | Load the most recent conversation in the current directory | `claude --continue` |53| `--continue`, `-c` | Load the most recent conversation in the current directory. Includes sessions that added this directory with `/add-dir` | `claude --continue` |

39| `--dangerously-skip-permissions` | Skip all permission prompts (use with caution) | `claude --dangerously-skip-permissions` |54| `--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` |

55| `--dangerously-skip-permissions` | Skip permission prompts. Equivalent to `--permission-mode bypassPermissions`. See [permission modes](/en/permission-modes#skip-all-checks-with-bypasspermissions-mode) for what this does and does not skip | `claude --dangerously-skip-permissions` |

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

41| `--disable-slash-commands` | Disable all skills and slash commands for this session | `claude --disable-slash-commands` |57| `--debug-file <path>` | Write debug logs to a specific file path. Implicitly enables debug mode. Takes precedence over `CLAUDE_CODE_DEBUG_LOGS_DIR` | `claude --debug-file /tmp/claude-debug.log` |

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

42| `--disallowedTools` | Tools that are removed from the model's context and cannot be used | `"Bash(git log *)" "Bash(git diff *)" "Edit"` |59| `--disallowedTools` | Tools that are removed from the model's context and cannot be used | `"Bash(git log *)" "Bash(git diff *)" "Edit"` |

60| `--effort` | Set the [effort level](/en/model-config#adjust-effort-level) for the current session. Options: `low`, `medium`, `high`, `xhigh`, `max`; available levels depend on the model. Session-scoped and does not persist to settings | `claude --effort high` |

61| `--enable-auto-mode` | {/* max-version: 2.1.110 */}Removed in v2.1.111. Auto mode is now in the `Shift+Tab` cycle by default; use `--permission-mode auto` to start in it | `claude --permission-mode auto` |

62| `--exclude-dynamic-system-prompt-sections` | Move per-machine sections from the system prompt (working directory, environment info, memory paths, git status) into the first user message. Improves prompt-cache reuse across different users and machines running the same task. Only applies with the default system prompt; ignored when `--system-prompt` or `--system-prompt-file` is set. Use with `-p` for scripted, multi-user workloads | `claude -p --exclude-dynamic-system-prompt-sections "query"` |

43| `--fallback-model` | Enable automatic fallback to specified model when default model is overloaded (print mode only) | `claude -p --fallback-model sonnet "query"` |63| `--fallback-model` | Enable automatic fallback to specified model when default model is overloaded (print mode only) | `claude -p --fallback-model sonnet "query"` |

44| `--fork-session` | When resuming, create a new session ID instead of reusing the original (use with `--resume` or `--continue`) | `claude --resume abc123 --fork-session` |64| `--fork-session` | When resuming, create a new session ID instead of reusing the original (use with `--resume` or `--continue`) | `claude --resume abc123 --fork-session` |

45| `--from-pr` | Resume sessions linked to a specific GitHub PR. Accepts a PR number or URL. Sessions are automatically linked when created via `gh pr create` | `claude --from-pr 123` |65| `--from-pr` | Resume sessions linked to a specific pull request. Accepts a PR number, a GitHub or GitHub Enterprise PR URL, a GitLab merge request URL, or a Bitbucket pull request URL. Sessions are linked automatically when Claude creates the pull request | `claude --from-pr 123` |

46| `--ide` | Automatically connect to IDE on startup if exactly one valid IDE is available | `claude --ide` |66| `--ide` | Automatically connect to IDE on startup if exactly one valid IDE is available | `claude --ide` |

47| `--init` | Run initialization hooks and start interactive mode | `claude --init` |67| `--init` | Run initialization hooks and start interactive mode | `claude --init` |

48| `--init-only` | Run initialization hooks and exit (no interactive session) | `claude --init-only` |68| `--init-only` | Run initialization hooks and exit (no interactive session) | `claude --init-only` |

49| `--include-partial-messages` | Include partial streaming events in output (requires `--print` and `--output-format=stream-json`) | `claude -p --output-format stream-json --include-partial-messages "query"` |69| `--include-hook-events` | Include all hook lifecycle events in the output stream. Requires `--output-format stream-json` | `claude -p --output-format stream-json --include-hook-events "query"` |

70| `--include-partial-messages` | Include partial streaming events in output. Requires `--print` and `--output-format stream-json` | `claude -p --output-format stream-json --include-partial-messages "query"` |

50| `--input-format` | Specify input format for print mode (options: `text`, `stream-json`) | `claude -p --output-format json --input-format stream-json` |71| `--input-format` | Specify input format for print mode (options: `text`, `stream-json`) | `claude -p --output-format json --input-format stream-json` |

51| `--json-schema` | Get validated JSON output matching a JSON Schema after agent completes its workflow (print mode only, see [Agent SDK Structured Outputs](https://docs.claude.com/en/docs/agent-sdk/structured-outputs)) | `claude -p --json-schema '{"type":"object","properties":{...}}' "query"` |72| `--json-schema` | Get validated JSON output matching a JSON Schema after agent completes its workflow (print mode only, see [structured outputs](/en/agent-sdk/structured-outputs)) | `claude -p --json-schema '{"type":"object","properties":{...}}' "query"` |

52| `--maintenance` | Run maintenance hooks and exit | `claude --maintenance` |73| `--maintenance` | Run maintenance hooks and start interactive mode | `claude --maintenance` |

53| `--max-budget-usd` | Maximum dollar amount to spend on API calls before stopping (print mode only) | `claude -p --max-budget-usd 5.00 "query"` |74| `--max-budget-usd` | Maximum dollar amount to spend on API calls before stopping (print mode only) | `claude -p --max-budget-usd 5.00 "query"` |

54| `--max-turns` | Limit the number of agentic turns (print mode only). Exits with an error when the limit is reached. No limit by default | `claude -p --max-turns 3 "query"` |75| `--max-turns` | Limit the number of agentic turns (print mode only). Exits with an error when the limit is reached. No limit by default | `claude -p --max-turns 3 "query"` |

55| `--mcp-config` | Load MCP servers from JSON files or strings (space-separated) | `claude --mcp-config ./mcp.json` |76| `--mcp-config` | Load MCP servers from JSON files or strings (space-separated) | `claude --mcp-config ./mcp.json` |

56| `--model` | Sets the model for the current session with an alias for the latest model (`sonnet` or `opus`) or a model's full name | `claude --model claude-sonnet-4-5-20250929` |77| `--model` | Sets the model for the current session with an alias for the latest model (`sonnet` or `opus`) or a model's full name | `claude --model claude-sonnet-4-6` |

78| `--name`, `-n` | Set a display name for the session, shown in `/resume` and the terminal title. You can resume a named session with `claude --resume <name>`. <br /><br />[`/rename`](/en/commands) changes the name mid-session and also shows it on the prompt bar | `claude -n "my-feature-work"` |

57| `--no-chrome` | Disable [Chrome browser integration](/en/chrome) for this session | `claude --no-chrome` |79| `--no-chrome` | Disable [Chrome browser integration](/en/chrome) for this session | `claude --no-chrome` |

58| `--no-session-persistence` | Disable session persistence so sessions are not saved to disk and cannot be resumed (print mode only) | `claude -p --no-session-persistence "query"` |80| `--no-session-persistence` | Disable session persistence so sessions are not saved to disk and cannot be resumed (print mode only) | `claude -p --no-session-persistence "query"` |

59| `--output-format` | Specify output format for print mode (options: `text`, `json`, `stream-json`) | `claude -p "query" --output-format json` |81| `--output-format` | Specify output format for print mode (options: `text`, `json`, `stream-json`) | `claude -p "query" --output-format json` |

60| `--permission-mode` | Begin in a specified [permission mode](/en/iam#permission-modes) | `claude --permission-mode plan` |82| `--permission-mode` | Begin in a specified [permission mode](/en/permission-modes). Accepts `default`, `acceptEdits`, `plan`, `auto`, `dontAsk`, or `bypassPermissions`. Overrides `defaultMode` from settings files | `claude --permission-mode plan` |

61| `--permission-prompt-tool` | Specify an MCP tool to handle permission prompts in non-interactive mode | `claude -p --permission-prompt-tool mcp_auth_tool "query"` |83| `--permission-prompt-tool` | Specify an MCP tool to handle permission prompts in non-interactive mode | `claude -p --permission-prompt-tool mcp_auth_tool "query"` |

62| `--plugin-dir` | Load plugins from directories for this session only (repeatable) | `claude --plugin-dir ./my-plugins` |84| `--plugin-dir` | Load plugins from a directory for this session only. Each flag takes one path. Repeat the flag for multiple directories: `--plugin-dir A --plugin-dir B` | `claude --plugin-dir ./my-plugins` |

63| `--print`, `-p` | Print response without interactive mode (see [SDK documentation](https://docs.claude.com/en/docs/agent-sdk) for programmatic usage details) | `claude -p "query"` |85| `--print`, `-p` | Print response without interactive mode (see [Agent SDK documentation](/en/agent-sdk/overview) for programmatic usage details) | `claude -p "query"` |

64| `--remote` | Create a new [web session](/en/claude-code-on-the-web) on claude.ai with the provided task description | `claude --remote "Fix the login bug"` |86| `--remote` | Create a new [web session](/en/claude-code-on-the-web) on claude.ai with the provided task description | `claude --remote "Fix the login bug"` |

65| `--resume`, `-r` | Resume a specific session by ID or name, or show an interactive picker to choose a session | `claude --resume auth-refactor` |87| `--remote-control`, `--rc` | Start an interactive session with [Remote Control](/en/remote-control#start-a-remote-control-session) enabled so you can also control it from claude.ai or the Claude app. Optionally pass a name for the session | `claude --remote-control "My Project"` |

88| `--remote-control-session-name-prefix <prefix>` | Prefix for auto-generated [Remote Control](/en/remote-control) session names when no explicit name is set. Defaults to your machine's hostname, producing names like `myhost-graceful-unicorn`. Set `CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX` for the same effect | `claude remote-control --remote-control-session-name-prefix dev-box` |

89| `--replay-user-messages` | Re-emit user messages from stdin back on stdout for acknowledgment. Requires `--input-format stream-json` and `--output-format stream-json` | `claude -p --input-format stream-json --output-format stream-json --replay-user-messages` |

90| `--resume`, `-r` | Resume a specific session by ID or name, or show an interactive picker to choose a session. Includes sessions that added this directory with `/add-dir` | `claude --resume auth-refactor` |

66| `--session-id` | Use a specific session ID for the conversation (must be a valid UUID) | `claude --session-id "550e8400-e29b-41d4-a716-446655440000"` |91| `--session-id` | Use a specific session ID for the conversation (must be a valid UUID) | `claude --session-id "550e8400-e29b-41d4-a716-446655440000"` |

67| `--setting-sources` | Comma-separated list of setting sources to load (`user`, `project`, `local`) | `claude --setting-sources user,project` |92| `--setting-sources` | Comma-separated list of setting sources to load (`user`, `project`, `local`) | `claude --setting-sources user,project` |

68| `--settings` | Path to a settings JSON file or a JSON string to load additional settings from | `claude --settings ./settings.json` |93| `--settings` | Path to a settings JSON file or a JSON string to load additional settings from | `claude --settings ./settings.json` |

69| `--strict-mcp-config` | Only use MCP servers from `--mcp-config`, ignoring all other MCP configurations | `claude --strict-mcp-config --mcp-config ./mcp.json` |94| `--strict-mcp-config` | Only use MCP servers from `--mcp-config`, ignoring all other MCP configurations | `claude --strict-mcp-config --mcp-config ./mcp.json` |

70| `--system-prompt` | Replace the entire system prompt with custom text (works in both interactive and print modes) | `claude --system-prompt "You are a Python expert"` |95| `--system-prompt` | Replace the entire system prompt with custom text | `claude --system-prompt "You are a Python expert"` |

71| `--system-prompt-file` | Load system prompt from a file, replacing the default prompt (print mode only) | `claude -p --system-prompt-file ./custom-prompt.txt "query"` |96| `--system-prompt-file` | Load system prompt from a file, replacing the default prompt | `claude --system-prompt-file ./custom-prompt.txt` |

72| `--teleport` | Resume a [web session](/en/claude-code-on-the-web) in your local terminal | `claude --teleport` |97| `--teleport` | Resume a [web session](/en/claude-code-on-the-web) in your local terminal | `claude --teleport` |

73| `--tools` | Restrict which built-in tools Claude can use (works in both interactive and print modes). Use `""` to disable all, `"default"` for all, or tool names like `"Bash,Edit,Read"` | `claude --tools "Bash,Edit,Read"` |98| `--teammate-mode` | Set how [agent team](/en/agent-teams) teammates display: `auto` (default), `in-process`, or `tmux`. See [Choose a display mode](/en/agent-teams#choose-a-display-mode) | `claude --teammate-mode in-process` |

74| `--verbose` | Enable verbose logging, shows full turn-by-turn output (helpful for debugging in both print and interactive modes) | `claude --verbose` |99| `--tmux` | Create a tmux session for the worktree. Requires `--worktree`. Uses iTerm2 native panes when available; pass `--tmux=classic` for traditional tmux | `claude -w feature-auth --tmux` |

100| `--tools` | Restrict which built-in tools Claude can use. Use `""` to disable all, `"default"` for all, or tool names like `"Bash,Edit,Read"` | `claude --tools "Bash,Edit,Read"` |

101| `--verbose` | Enable verbose logging, shows full turn-by-turn output | `claude --verbose` |

75| `--version`, `-v` | Output the version number | `claude -v` |102| `--version`, `-v` | Output the version number | `claude -v` |

76 103| `--worktree`, `-w` | Start Claude in an isolated [git worktree](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees) at `<repo>/.claude/worktrees/<name>`. If no name is given, one is auto-generated | `claude -w feature-auth` |

77<Tip>

78 The `--output-format json` flag is particularly useful for scripting and

79 automation, allowing you to parse Claude's responses programmatically.

80</Tip>

81 

82### Agents flag format

83 

84The `--agents` flag accepts a JSON object that defines one or more custom subagents. Each subagent requires a unique name (as the key) and a definition object with the following fields:

85 

86| Field | Required | Description |

87| :------------ | :------- | :---------------------------------------------------------------------------------------------------------------------------------- |

88| `description` | Yes | Natural language description of when the subagent should be invoked |

89| `prompt` | Yes | The system prompt that guides the subagent's behavior |

90| `tools` | No | Array of specific tools the subagent can use (for example, `["Read", "Edit", "Bash"]`). If omitted, inherits all tools |

91| `model` | No | Model alias to use: `sonnet`, `opus`, `haiku`, or `inherit`. If omitted, defaults to `inherit` (uses the main conversation's model) |

92 

93Example:

94 

95```bash theme={null}

96claude --agents '{

97 "code-reviewer": {

98 "description": "Expert code reviewer. Use proactively after code changes.",

99 "prompt": "You are a senior code reviewer. Focus on code quality, security, and best practices.",

100 "tools": ["Read", "Grep", "Glob", "Bash"],

101 "model": "sonnet"

102 },

103 "debugger": {

104 "description": "Debugging specialist for errors and test failures.",

105 "prompt": "You are an expert debugger. Analyze errors, identify root causes, and provide fixes."

106 }

107}'

108```

109 

110For more details on creating and using subagents, see the [subagents documentation](/en/sub-agents).

111 104 

112### System prompt flags105### System prompt flags

113 106 

114Claude Code provides four flags for customizing the system prompt, each serving a different purpose:107Claude Code provides four flags for customizing the system prompt. All four work in both interactive and non-interactive modes.

115 

116| Flag | Behavior | Modes | Use Case |

117| :---------------------------- | :------------------------------------------ | :------------------ | :------------------------------------------------------------------- |

118| `--system-prompt` | **Replaces** entire default prompt | Interactive + Print | Complete control over Claude's behavior and instructions |

119| `--system-prompt-file` | **Replaces** with file contents | Print only | Load prompts from files for reproducibility and version control |

120| `--append-system-prompt` | **Appends** to default prompt | Interactive + Print | Add specific instructions while keeping default Claude Code behavior |

121| `--append-system-prompt-file` | **Appends** file contents to default prompt | Print only | Load additional instructions from files while keeping defaults |

122 

123**When to use each:**

124 

125* **`--system-prompt`**: Use when you need complete control over Claude's system prompt. This removes all default Claude Code instructions, giving you a blank slate.

126 ```bash theme={null}

127 claude --system-prompt "You are a Python expert who only writes type-annotated code"

128 ```

129 

130* **`--system-prompt-file`**: Use when you want to load a custom prompt from a file, useful for team consistency or version-controlled prompt templates.

131 ```bash theme={null}

132 claude -p --system-prompt-file ./prompts/code-review.txt "Review this PR"

133 ```

134 

135* **`--append-system-prompt`**: Use when you want to add specific instructions while keeping Claude Code's default capabilities intact. This is the safest option for most use cases.

136 ```bash theme={null}

137 claude --append-system-prompt "Always use TypeScript and include JSDoc comments"

138 ```

139 108 

140* **`--append-system-prompt-file`**: Use when you want to append instructions from a file while keeping Claude Code's defaults. Useful for version-controlled additions.109| Flag | Behavior | Example |

141 ```bash theme={null}110| :---------------------------- | :------------------------------------------ | :------------------------------------------------------ |

142 claude -p --append-system-prompt-file ./prompts/style-rules.txt "Review this PR"111| `--system-prompt` | Replaces the entire default prompt | `claude --system-prompt "You are a Python expert"` |

143 ```112| `--system-prompt-file` | Replaces with file contents | `claude --system-prompt-file ./prompts/review.txt` |

113| `--append-system-prompt` | Appends to the default prompt | `claude --append-system-prompt "Always use TypeScript"` |

114| `--append-system-prompt-file` | Appends file contents to the default prompt | `claude --append-system-prompt-file ./style-rules.txt` |

144 115 

145`--system-prompt` and `--system-prompt-file` are mutually exclusive. The append flags can be used together with either replacement flag.116`--system-prompt` and `--system-prompt-file` are mutually exclusive. The append flags can be combined with either replacement flag.

146 117 

147For most use cases, `--append-system-prompt` or `--append-system-prompt-file` is recommended as they preserve Claude Code's built-in capabilities while adding your custom requirements. Use `--system-prompt` or `--system-prompt-file` only when you need complete control over the system prompt.118For most use cases, use an append flag. Appending preserves Claude Code's built-in capabilities while adding your requirements. Use a replacement flag only when you need complete control over the system prompt.

148 119 

149## See also120## See also

150 121 


153* [Quickstart guide](/en/quickstart) - Getting started with Claude Code124* [Quickstart guide](/en/quickstart) - Getting started with Claude Code

154* [Common workflows](/en/common-workflows) - Advanced workflows and patterns125* [Common workflows](/en/common-workflows) - Advanced workflows and patterns

155* [Settings](/en/settings) - Configuration options126* [Settings](/en/settings) - Configuration options

156* [SDK documentation](https://docs.claude.com/en/docs/agent-sdk) - Programmatic usage and integrations127* [Agent SDK documentation](/en/agent-sdk/overview) - Programmatic usage and integrations

code-review.md +281 −0 added

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# Code Review

6 

7> Set up automated PR reviews that catch logic errors, security vulnerabilities, and regressions using multi-agent analysis of your full codebase

8 

9<Note>

10 Code Review is in research preview, available for [Team and Enterprise](https://claude.ai/admin-settings/claude-code) subscriptions. It is not available for organizations with [Zero Data Retention](/en/zero-data-retention) enabled.

11</Note>

12 

13Code Review analyzes your GitHub pull requests and posts findings as inline comments on the lines of code where it found issues. A fleet of specialized agents examine the code changes in the context of your full codebase, looking for logic errors, security vulnerabilities, broken edge cases, and subtle regressions.

14 

15Findings are tagged by severity and don't approve or block your PR, so existing review workflows stay intact. You can tune what Claude flags by adding a `CLAUDE.md` or `REVIEW.md` file to your repository.

16 

17To run Claude in your own CI infrastructure instead of this managed service, see [GitHub Actions](/en/github-actions) or [GitLab CI/CD](/en/gitlab-ci-cd). For repositories on a self-hosted GitHub instance, see [GitHub Enterprise Server](/en/github-enterprise-server).

18 

19This page covers:

20 

21* [How reviews work](#how-reviews-work)

22* [Setup](#set-up-code-review)

23* [Triggering reviews manually](#manually-trigger-reviews) with `@claude review` and `@claude review once`

24* [Customizing reviews](#customize-reviews) with `CLAUDE.md` and `REVIEW.md`

25* [Pricing](#pricing)

26* [Troubleshooting](#troubleshooting) failed runs and missing comments

27 

28## How reviews work

29 

30Once an admin [enables Code Review](#set-up-code-review) for your organization, reviews trigger when a PR opens, on every push, or when manually requested, depending on the repository's configured behavior. Commenting `@claude review` [starts reviews on a PR](#manually-trigger-reviews) in any mode.

31 

32When a review runs, multiple agents analyze the diff and surrounding code in parallel on Anthropic infrastructure. Each agent looks for a different class of issue, then a verification step checks candidates against actual code behavior to filter out false positives. The results are deduplicated, ranked by severity, and posted as inline comments on the specific lines where issues were found, with a summary in the review body. If no issues are found, Claude posts a short confirmation comment on the PR.

33 

34Reviews scale in cost with PR size and complexity, completing in 20 minutes on average. Admins can monitor review activity and spend via the [analytics dashboard](#view-usage).

35 

36### Severity levels

37 

38Each finding is tagged with a severity level:

39 

40| Marker | Severity | Meaning |

41| :----- | :----------- | :------------------------------------------------------------------ |

42| 🔴 | Important | A bug that should be fixed before merging |

43| 🟡 | Nit | A minor issue, worth fixing but not blocking |

44| 🟣 | Pre-existing | A bug that exists in the codebase but was not introduced by this PR |

45 

46Findings include a collapsible extended reasoning section you can expand to understand why Claude flagged the issue and how it verified the problem.

47 

48### Rate and reply to findings

49 

50Each review comment from Claude arrives with 👍 and 👎 already attached so both buttons appear in the GitHub UI for one-click rating. Click 👍 if the finding was useful or 👎 if it was wrong or noisy. Anthropic collects reaction counts after the PR merges and uses them to tune the reviewer. Reactions do not trigger a re-review or change anything on the PR.

51 

52Replying to an inline comment does not prompt Claude to respond or update the PR. To act on a finding, fix the code and push. If the PR is subscribed to push-triggered reviews, the next run resolves the thread when the issue is fixed. To request a fresh review without pushing, comment `@claude review once` as a [top-level PR comment](#manually-trigger-reviews).

53 

54### Check run output

55 

56Beyond the inline review comments, each review populates the **Claude Code Review** check run that appears alongside your CI checks. Expand its **Details** link to see a summary of every finding in one place, sorted by severity:

57 

58| Severity | File:Line | Issue |

59| ------------ | ------------------------- | -------------------------------------------------------------- |

60| 🔴 Important | `src/auth/session.ts:142` | Token refresh races with logout, leaving stale sessions active |

61| 🟡 Nit | `src/auth/session.ts:88` | `parseExpiry` silently returns 0 on malformed input |

62 

63Each finding also appears as an annotation in the **Files changed** tab, marked directly on the relevant diff lines. Important findings render with a red marker, nits with a yellow warning, and pre-existing bugs with a gray notice. Annotations and the severity table are written to the check run independently of inline review comments, so they remain available even if GitHub rejects an inline comment on a line that moved.

64 

65The check run always completes with a neutral conclusion so it never blocks merging through branch protection rules. If you want to gate merges on Code Review findings, read the severity breakdown from the check run output in your own CI. The last line of the Details text is a machine-readable comment your workflow can parse with `gh` and jq:

66 

67```bash theme={null}

68gh api repos/OWNER/REPO/check-runs/CHECK_RUN_ID \

69 --jq '.output.text | split("bughunter-severity: ")[1] | split(" -->")[0] | fromjson'

70```

71 

72This returns a JSON object with counts per severity, for example `{"normal": 2, "nit": 1, "pre_existing": 0}`. The `normal` key holds the count of Important findings; a non-zero value means Claude found at least one bug worth fixing before merge.

73 

74### What Code Review checks

75 

76By default, Code Review focuses on correctness: bugs that would break production, not formatting preferences or missing test coverage. You can expand what it checks by [adding guidance files](#customize-reviews) to your repository.

77 

78## Set up Code Review

79 

80An admin enables Code Review once for the organization and selects which repositories to include.

81 

82<Steps>

83 <Step title="Open Claude Code admin settings">

84 Go to [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code) and find the Code Review section. You need admin access to your Claude organization and permission to install GitHub Apps in your GitHub organization.

85 </Step>

86 

87 <Step title="Start setup">

88 Click **Setup**. This begins the GitHub App installation flow.

89 </Step>

90 

91 <Step title="Install the Claude GitHub App">

92 Follow the prompts to install the Claude GitHub App to your GitHub organization. The app requests these repository permissions:

93 

94 * **Contents**: read and write

95 * **Issues**: read and write

96 * **Pull requests**: read and write

97 

98 Code Review uses read access to contents and write access to pull requests. The broader permission set also supports [GitHub Actions](/en/github-actions) if you enable that later.

99 </Step>

100 

101 <Step title="Select repositories">

102 Choose which repositories to enable for Code Review. If you don't see a repository, make sure you gave the Claude GitHub App access to it during installation. You can add more repositories later.

103 </Step>

104 

105 <Step title="Set review triggers per repo">

106 After setup completes, the Code Review section shows your repositories in a table. For each repository, use the **Review Behavior** dropdown to choose when reviews run:

107 

108 * **Once after PR creation**: review runs once when a PR is opened or marked ready for review

109 * **After every push**: review runs on every push to the PR branch, catching new issues as the PR evolves and auto-resolving threads when you fix flagged issues

110 * **Manual**: reviews start only when someone [comments `@claude review` or `@claude review once` on a PR](#manually-trigger-reviews); `@claude review` also subscribes the PR to reviews on subsequent pushes

111 

112 Reviewing on every push runs the most reviews and costs the most. Manual mode is useful for high-traffic repos where you want to opt specific PRs into review, or to only start reviewing your PRs once they're ready.

113 </Step>

114</Steps>

115 

116The repositories table also shows the average cost per review for each repo based on recent activity. Use the row actions menu to turn Code Review on or off per repository, or to remove a repository entirely.

117 

118To verify setup, open a test PR. If you chose an automatic trigger, a check run named **Claude Code Review** appears within a few minutes. If you chose Manual, comment `@claude review` on the PR to start the first review. If no check run appears, confirm the repository is listed in your admin settings and the Claude GitHub App has access to it.

119 

120## Manually trigger reviews

121 

122Two comment commands start a review on demand. Both work regardless of the repository's configured trigger, so you can use them to opt specific PRs into review in Manual mode or to get an immediate re-review in other modes.

123 

124| Command | What it does |

125| :-------------------- | :---------------------------------------------------------------------------- |

126| `@claude review` | Starts a review and subscribes the PR to push-triggered reviews going forward |

127| `@claude review once` | Starts a single review without subscribing the PR to future pushes |

128 

129Use `@claude review once` when you want feedback on the current state of a PR but don't want every subsequent push to incur a review. This is useful for long-running PRs with frequent pushes, or when you want a one-off second opinion without changing the PR's review behavior.

130 

131For either command to trigger a review:

132 

133* Post it as a top-level PR comment, not an inline comment on a diff line

134* Put the command at the start of the comment, with `once` on the same line if you're using the one-shot form

135* You must have owner, member, or collaborator access to the repository

136* The PR must be open

137 

138Unlike automatic triggers, manual triggers run on draft PRs, since an explicit request signals you want the review now regardless of draft status.

139 

140If a review is already running on that PR, the request is queued until the in-progress review completes. You can monitor progress via the check run on the PR.

141 

142## Customize reviews

143 

144Code Review reads two files from your repository to guide what it flags. They differ in how strongly they influence the review:

145 

146* **`CLAUDE.md`**: shared project instructions that Claude Code uses for all tasks, not just reviews. Code Review reads it as project context and flags newly introduced violations as nits.

147* **`REVIEW.md`**: review-only instructions, injected directly into every agent in the review pipeline as highest priority. Use it to change what gets flagged, at what severity, and how findings are reported.

148 

149### CLAUDE.md

150 

151Code Review reads your repository's `CLAUDE.md` files and treats newly introduced violations as [nit-level](#severity-levels) findings. This works bidirectionally: if your PR changes code in a way that makes a `CLAUDE.md` statement outdated, Claude flags that the docs need updating too.

152 

153Claude reads `CLAUDE.md` files at every level of your directory hierarchy, so rules in a subdirectory's `CLAUDE.md` apply only to files under that path. See the [memory documentation](/en/memory) for more on how `CLAUDE.md` works.

154 

155For review-specific guidance that you don't want applied to general Claude Code sessions, use [`REVIEW.md`](#review-md) instead.

156 

157### REVIEW\.md

158 

159`REVIEW.md` is a file at your repository root that overrides how Code Review behaves on your repo. Its contents are injected into the system prompt of every agent in the review pipeline as the highest-priority instruction block, taking precedence over the default review guidance.

160 

161Because it's pasted verbatim, `REVIEW.md` is plain instructions: [`@` import syntax](/en/memory#import-additional-files) is not expanded, and referenced files are not read into the prompt. Put the rules you want enforced directly in the file.

162 

163#### What you can tune

164 

165`REVIEW.md` is freeform markdown, so anything you can express as a review instruction is in scope. The patterns below have the most impact in practice.

166 

167**Severity**: redefine what 🔴 Important means for your repo. The default calibration targets production code; a docs repo, a config repo, or a prototype might want a much narrower definition. State explicitly which classes of finding are Important and which are Nit at most. You can also escalate in the other direction, for example treating any `CLAUDE.md` violation as Important rather than the default nit.

168 

169**Nit volume**: cap how many 🟡 Nit comments a single review posts. Prose and config files can be polished forever. A cap like "report at most five nits, mention the rest as a count in the summary" keeps reviews actionable.

170 

171**Skip rules**: list paths, branch patterns, and finding categories where Claude should post no findings. Common candidates are generated code, lockfiles, vendored dependencies, and machine-authored branches, along with anything your CI already enforces like linting or spellcheck. For paths that warrant some review but not full scrutiny, set a higher bar instead of skipping entirely: "in `scripts/`, only report if near-certain and severe."

172 

173**Repo-specific checks**: add rules you want flagged on every PR, like "new API routes must have an integration test." Because `REVIEW.md` is injected as highest priority, these land more reliably than the same rules in a long `CLAUDE.md`.

174 

175**Verification bar**: require evidence before a class of finding is posted. For example, "behavior claims need a `file:line` citation in the source, not an inference from naming" cuts false positives that would otherwise cost the author a round trip.

176 

177**Re-review convergence**: tell Claude how to behave when a PR has already been reviewed. A rule like "after the first review, suppress new nits and post Important findings only" stops a one-line fix from reaching round seven on style alone.

178 

179**Summary shape**: ask for the review body to open with a one-line tally such as `2 factual, 4 style`, and to lead with "no factual issues" when that's the case. The author wants to know the shape of the work before the details.

180 

181#### Example

182 

183This `REVIEW.md` recalibrates severity for a backend service, caps nits, skips generated files, and adds repo-specific checks.

184 

185```markdown theme={null}

186# Review instructions

187 

188## What Important means here

189 

190Reserve Important for findings that would break behavior, leak data,

191or block a rollback: incorrect logic, unscoped database queries, PII

192in logs or error messages, and migrations that aren't backward

193compatible. Style, naming, and refactoring suggestions are Nit at

194most.

195 

196## Cap the nits

197 

198Report at most five Nits per review. If you found more, say "plus N

199similar items" in the summary instead of posting them inline. If

200everything you found is a Nit, lead the summary with "No blocking

201issues."

202 

203## Do not report

204 

205- Anything CI already enforces: lint, formatting, type errors

206- Generated files under `src/gen/` and any `*.lock` file

207- Test-only code that intentionally violates production rules

208 

209## Always check

210 

211- New API routes have an integration test

212- Log lines don't include email addresses, user IDs, or request bodies

213- Database queries are scoped to the caller's tenant

214```

215 

216#### Keep it focused

217 

218Length has a cost: a long `REVIEW.md` dilutes the rules that matter most. Keep it to instructions that change review behavior, and leave general project context in `CLAUDE.md`.

219 

220## View usage

221 

222Go to [claude.ai/analytics/code-review](https://claude.ai/analytics/code-review) to see Code Review activity across your organization. The dashboard shows:

223 

224| Section | What it shows |

225| :------------------- | :--------------------------------------------------------------------------------------- |

226| PRs reviewed | Daily count of pull requests reviewed over the selected time range |

227| Cost weekly | Weekly spend on Code Review |

228| Feedback | Count of review comments that were auto-resolved because a developer addressed the issue |

229| Repository breakdown | Per-repo counts of PRs reviewed and comments resolved |

230 

231The repositories table in admin settings also shows average cost per review for each repo. Dashboard cost figures are estimates for monitoring activity; for invoice-accurate spend, refer to your Anthropic bill.

232 

233## Pricing

234 

235Code Review is billed based on token usage. Each review averages \$15-25 in cost, scaling with PR size, codebase complexity, and how many issues require verification. Code Review usage is billed separately through [extra usage](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) and does not count against your plan's included usage.

236 

237The review trigger you choose affects total cost:

238 

239* **Once after PR creation**: runs once per PR

240* **After every push**: runs on each push, multiplying cost by the number of pushes

241* **Manual**: no reviews until someone comments `@claude review` on a PR

242 

243In any mode, commenting `@claude review` [opts the PR into push-triggered reviews](#manually-trigger-reviews), so additional cost accrues per push after that comment. To run a single review without subscribing to future pushes, comment `@claude review once` instead.

244 

245Costs appear on your Anthropic bill regardless of whether your organization uses AWS Bedrock or Google Vertex AI for other Claude Code features. To set a monthly spend cap for Code Review, go to [claude.ai/admin-settings/usage](https://claude.ai/admin-settings/usage) and configure the limit for the Claude Code Review service.

246 

247Monitor spend via the weekly cost chart in [analytics](#view-usage) or the per-repo average cost column in admin settings.

248 

249## Troubleshooting

250 

251Review runs are best-effort. A failed run never blocks your PR, but it also doesn't retry on its own. This section covers how to recover from a failed run and where to look when the check run reports issues you can't find.

252 

253### Retrigger a failed or timed-out review

254 

255When the review infrastructure hits an internal error or exceeds its time limit, the check run completes with a title of **Code review encountered an error** or **Code review timed out**. The conclusion is still neutral, so nothing blocks your merge, but no findings are posted.

256 

257To run the review again, comment `@claude review once` on the PR. This starts a fresh review without subscribing the PR to future pushes. If the PR is already subscribed to push-triggered reviews, pushing a new commit also starts a new review.

258 

259The **Re-run** button in GitHub's Checks tab does not retrigger Code Review. Use the comment command or a new push instead.

260 

261### Review didn't run and the PR shows a spend-cap message

262 

263When your organization's monthly spend cap is reached, Code Review posts a single comment on the PR explaining that the review was skipped. Reviews resume automatically at the start of the next billing period, or immediately when an admin raises the cap at [claude.ai/admin-settings/usage](https://claude.ai/admin-settings/usage).

264 

265### Find issues that aren't showing as inline comments

266 

267If the check run title says issues were found but you don't see inline review comments on the diff, look in these other locations where findings are surfaced:

268 

269* **Check run Details**: click **Details** next to the Claude Code Review check in the Checks tab. The severity table lists every finding with its file, line, and summary regardless of whether the inline comment was accepted.

270* **Files changed annotations**: open the **Files changed** tab on the PR. Findings render as annotations attached directly to the diff lines, separate from review comments.

271* **Review body**: if you pushed to the PR while a review was running, some findings may reference lines that no longer exist in the current diff. Those appear under an **Additional findings** heading in the review body text rather than as inline comments.

272 

273## Related resources

274 

275Code Review is designed to work alongside the rest of Claude Code. If you want to run reviews locally before opening a PR, need a self-hosted setup, or want to go deeper on how `CLAUDE.md` shapes Claude's behavior across tools, these pages are good next stops:

276 

277* [Plugins](/en/discover-plugins): browse the plugin marketplace, including a `code-review` plugin for running on-demand reviews locally before pushing

278* [GitHub Actions](/en/github-actions): run Claude in your own GitHub Actions workflows for custom automation beyond code review

279* [GitLab CI/CD](/en/gitlab-ci-cd): self-hosted Claude integration for GitLab pipelines

280* [Memory](/en/memory): how `CLAUDE.md` files work across Claude Code

281* [Analytics](/en/analytics): track Claude Code usage beyond code review

commands.md +113 −0 added

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# Commands

6 

7> Complete reference for commands available in Claude Code, including built-in commands and bundled skills.

8 

9Commands control Claude Code from inside a session. They provide a quick way to switch models, manage permissions, clear context, run a workflow, and more.

10 

11Type `/` to see every command available to you, or type `/` followed by letters to filter.

12 

13The table below lists all the commands included in Claude Code. Entries marked **[Skill](/en/skills#bundled-skills)** are bundled skills. They use the same mechanism as skills you write yourself: a prompt handed to Claude, which Claude can also invoke automatically when relevant. Everything else is a built-in command whose behavior is coded into the CLI. To add your own commands, see [skills](/en/skills).

14 

15Not every command appears for every user. Availability depends on your platform, plan, and environment. For example, `/desktop` only shows on macOS and Windows, and `/upgrade` only shows on Pro and Max plans.

16 

17In the table below, `<arg>` indicates a required argument and `[arg]` indicates an optional one.

18 

19| Command | Purpose |

20| :---------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

21| `/add-dir <path>` | Add a working directory for file access during the current session. Most `.claude/` configuration is [not discovered](/en/permissions#additional-directories-grant-file-access-not-configuration) from the added directory. You can later resume the session from the added directory with `--continue` or `--resume` |

22| `/agents` | Manage [agent](/en/sub-agents) configurations |

23| `/autofix-pr [prompt]` | Spawn a [Claude Code on the web](/en/claude-code-on-the-web#auto-fix-pull-requests) session that watches the current branch's PR and pushes fixes when CI fails or reviewers leave comments. Detects the open PR from your checked-out branch with `gh pr view`; to watch a different PR, check out its branch first. By default the remote session is told to fix every CI failure and review comment; pass a prompt to give it different instructions, for example `/autofix-pr only fix lint and type errors`. Requires the `gh` CLI and access to [Claude Code on the web](/en/claude-code-on-the-web#who-can-use-claude-code-on-the-web) |

24| `/batch <instruction>` | **[Skill](/en/skills#bundled-skills).** Orchestrate large-scale changes across a codebase in parallel. Researches the codebase, decomposes the work into 5 to 30 independent units, and presents a plan. Once approved, spawns one background agent per unit in an isolated [git worktree](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees). Each agent implements its unit, runs tests, and opens a pull request. Requires a git repository. Example: `/batch migrate src/ from Solid to React` |

25| `/branch [name]` | Create a branch of the current conversation at this point. Switches you into the branch and preserves the original, which you can return to with `/resume`. Alias: `/fork`. When [`CLAUDE_CODE_FORK_SUBAGENT`](/en/env-vars) is set, `/fork` instead spawns a [forked subagent](/en/sub-agents#fork-the-current-conversation) and is no longer an alias for this command |

26| `/btw <question>` | Ask a quick [side question](/en/interactive-mode#side-questions-with-%2Fbtw) without adding to the conversation |

27| `/chrome` | Configure [Claude in Chrome](/en/chrome) settings |

28| `/claude-api [migrate\|managed-agents-onboard]` | **[Skill](/en/skills#bundled-skills).** Load Claude API reference material for your project's language (Python, TypeScript, Java, Go, Ruby, C#, PHP, or cURL) and Managed Agents reference. Covers tool use, streaming, batches, structured outputs, and common pitfalls. Also activates automatically when your code imports `anthropic` or `@anthropic-ai/sdk`. Run `/claude-api migrate` to upgrade existing Claude API code to a newer model: Claude asks which files to scan and which model to target, then updates model IDs, thinking configuration, and other parameters that changed between versions. Run `/claude-api managed-agents-onboard` for an interactive walkthrough that creates a new Managed Agent from scratch |

29| `/clear` | Start a new conversation with empty context. The previous conversation stays available in `/resume`. To free up context while continuing the same conversation, use `/compact` instead. Aliases: `/reset`, `/new` |

30| `/color [color\|default]` | Set the prompt bar color for the current session. Available colors: `red`, `blue`, `green`, `yellow`, `purple`, `orange`, `pink`, `cyan`. Use `default` to reset. When [Remote Control](/en/remote-control) is connected, the color syncs to claude.ai/code |

31| `/compact [instructions]` | Free up context by summarizing the conversation so far. Optionally pass focus instructions for the summary. See [how compaction handles rules, skills, and memory files](/en/context-window#what-survives-compaction) |

32| `/config` | Open the [Settings](/en/settings) interface to adjust theme, model, [output style](/en/output-styles), and other preferences. Alias: `/settings` |

33| `/context` | Visualize current context usage as a colored grid. Shows optimization suggestions for context-heavy tools, memory bloat, and capacity warnings |

34| `/copy [N]` | Copy the last assistant response to clipboard. Pass a number `N` to copy the Nth-latest response: `/copy 2` copies the second-to-last. When code blocks are present, shows an interactive picker to select individual blocks or the full response. Press `w` in the picker to write the selection to a file instead of the clipboard, which is useful over SSH |

35| `/cost` | Alias for `/usage` |

36| `/debug [description]` | **[Skill](/en/skills#bundled-skills).** Enable debug logging for the current session and troubleshoot issues by reading the session debug log. Debug logging is off by default unless you started with `claude --debug`, so running `/debug` mid-session starts capturing logs from that point forward. Optionally describe the issue to focus the analysis |

37| `/desktop` | Continue the current session in the Claude Code Desktop app. macOS and Windows only. Alias: `/app` |

38| `/diff` | Open an interactive diff viewer showing uncommitted changes and per-turn diffs. Use left/right arrows to switch between the current git diff and individual Claude turns, and up/down to browse files |

39| `/doctor` | Diagnose and verify your Claude Code installation and settings. Results show with status icons. Press `f` to have Claude fix any reported issues |

40| `/effort [level\|auto]` | Set the model [effort level](/en/model-config#adjust-effort-level). Accepts `low`, `medium`, `high`, `xhigh`, or `max`; available levels depend on the model and `max` is session-only. `auto` resets to the model default. Without an argument, opens an interactive slider; use left and right arrows to pick a level and `Enter` to apply. Takes effect immediately without waiting for the current response to finish |

41| `/exit` | Exit the CLI. Alias: `/quit` |

42| `/export [filename]` | Export the current conversation as plain text. With a filename, writes directly to that file. Without, opens a dialog to copy to clipboard or save to a file |

43| `/extra-usage` | Configure extra usage to keep working when rate limits are hit |

44| `/fast [on\|off]` | Toggle [fast mode](/en/fast-mode) on or off |

45| `/feedback [report]` | Submit feedback about Claude Code. Alias: `/bug` |

46| `/fewer-permission-prompts` | **[Skill](/en/skills#bundled-skills).** Scan your transcripts for common read-only Bash and MCP tool calls, then add a prioritized allowlist to project `.claude/settings.json` to reduce permission prompts |

47| `/focus` | Toggle the focus view, which shows only your last prompt, a one-line tool-call summary with edit diffstats, and the final response. The selection persists across sessions. Only available in [fullscreen rendering](/en/fullscreen) |

48| `/heapdump` | Write a JavaScript heap snapshot and a memory breakdown to `~/Desktop` for diagnosing high memory usage. See [troubleshooting](/en/troubleshooting#high-cpu-or-memory-usage) |

49| `/help` | Show help and available commands |

50| `/hooks` | View [hook](/en/hooks) configurations for tool events |

51| `/ide` | Manage IDE integrations and show status |

52| `/init` | Initialize project with a `CLAUDE.md` guide. Set `CLAUDE_CODE_NEW_INIT=1` for an interactive flow that also walks through skills, hooks, and personal memory files |

53| `/insights` | Generate a report analyzing your Claude Code sessions, including project areas, interaction patterns, and friction points |

54| `/install-github-app` | Set up the [Claude GitHub Actions](/en/github-actions) app for a repository. Walks you through selecting a repo and configuring the integration |

55| `/install-slack-app` | Install the Claude Slack app. Opens a browser to complete the OAuth flow |

56| `/keybindings` | Open or create your keybindings configuration file |

57| `/login` | Sign in to your Anthropic account |

58| `/logout` | Sign out from your Anthropic account |

59| `/loop [interval] [prompt]` | **[Skill](/en/skills#bundled-skills).** Run a prompt repeatedly while the session stays open. Omit the interval and Claude self-paces between iterations. Omit the prompt and Claude runs an autonomous maintenance check, or the prompt in `.claude/loop.md` if present. Example: `/loop 5m check if the deploy finished`. See [Run prompts on a schedule](/en/scheduled-tasks). Alias: `/proactive` |

60| `/mcp` | Manage MCP server connections and OAuth authentication |

61| `/memory` | Edit `CLAUDE.md` memory files, enable or disable [auto-memory](/en/memory#auto-memory), and view auto-memory entries |

62| `/mobile` | Show QR code to download the Claude mobile app. Aliases: `/ios`, `/android` |

63| `/model [model]` | Select or change the AI model. For models that support it, use left/right arrows to [adjust effort level](/en/model-config#adjust-effort-level). With no argument, opens a picker that asks for confirmation when the conversation has prior output, since the next response re-reads the full history without cached context. Once confirmed, the change applies without waiting for the current response to finish |

64| `/passes` | Share a free week of Claude Code with friends. Only visible if your account is eligible |

65| `/permissions` | Manage allow, ask, and deny rules for tool permissions. Opens an interactive dialog where you can view rules by scope, add or remove rules, manage working directories, and review [recent auto mode denials](/en/auto-mode-config#review-denials). Alias: `/allowed-tools` |

66| `/plan [description]` | Enter plan mode directly from the prompt. Pass an optional description to enter plan mode and immediately start with that task, for example `/plan fix the auth bug` |

67| `/plugin` | Manage Claude Code [plugins](/en/plugins) |

68| `/powerup` | Discover Claude Code features through quick interactive lessons with animated demos |

69| `/pr-comments [PR]` | {/* max-version: 2.1.90 */}Removed in v2.1.91. Ask Claude directly to view pull request comments instead. On earlier versions, fetches and displays comments from a GitHub pull request; automatically detects the PR for the current branch, or pass a PR URL or number. Requires the `gh` CLI |

70| `/privacy-settings` | View and update your privacy settings. Only available for Pro and Max plan subscribers |

71| `/recap` | Generate a one-line summary of the current session on demand. See [Session recap](/en/interactive-mode#session-recap) for the automatic recap that appears after you've been away |

72| `/release-notes` | View the changelog in an interactive version picker. Select a specific version to see its release notes, or choose to show all versions |

73| `/reload-plugins` | Reload all active [plugins](/en/plugins) to apply pending changes without restarting. Reports counts for each reloaded component and flags any load errors |

74| `/remote-control` | Make this session available for [remote control](/en/remote-control) from claude.ai. Alias: `/rc` |

75| `/remote-env` | Configure the default remote environment for [web sessions started with `--remote`](/en/claude-code-on-the-web#configure-your-environment) |

76| `/rename [name]` | Rename the current session and show the name on the prompt bar. Without a name, auto-generates one from conversation history |

77| `/resume [session]` | Resume a conversation by ID or name, or open the session picker. Alias: `/continue` |

78| `/review [PR]` | Review a pull request locally in your current session. For a deeper cloud-based review, see [`/ultrareview`](/en/ultrareview) |

79| `/rewind` | Rewind the conversation and/or code to a previous point, or summarize from a selected message. See [checkpointing](/en/checkpointing). Aliases: `/checkpoint`, `/undo` |

80| `/sandbox` | Toggle [sandbox mode](/en/sandboxing). Available on supported platforms only |

81| `/schedule [description]` | Create, update, list, or run [routines](/en/routines). Claude walks you through the setup conversationally. Alias: `/routines` |

82| `/security-review` | Analyze pending changes on the current branch for security vulnerabilities. Reviews the git diff and identifies risks like injection, auth issues, and data exposure |

83| `/setup-bedrock` | Configure [Amazon Bedrock](/en/amazon-bedrock) authentication, region, and model pins through an interactive wizard. Only visible when `CLAUDE_CODE_USE_BEDROCK=1` is set. First-time Bedrock users can also access this wizard from the login screen |

84| `/setup-vertex` | Configure [Google Vertex AI](/en/google-vertex-ai) authentication, project, region, and model pins through an interactive wizard. Only visible when `CLAUDE_CODE_USE_VERTEX=1` is set. First-time Vertex AI users can also access this wizard from the login screen |

85| `/simplify [focus]` | **[Skill](/en/skills#bundled-skills).** Review your recently changed files for code reuse, quality, and efficiency issues, then fix them. Spawns three review agents in parallel, aggregates their findings, and applies fixes. Pass text to focus on specific concerns: `/simplify focus on memory efficiency` |

86| `/skills` | List available [skills](/en/skills). Press `t` to sort by token count |

87| `/stats` | Alias for `/usage`. Opens on the Stats tab |

88| `/status` | Open the Settings interface (Status tab) showing version, model, account, and connectivity. Works while Claude is responding, without waiting for the current response to finish |

89| `/statusline` | Configure Claude Code's [status line](/en/statusline). Describe what you want, or run without arguments to auto-configure from your shell prompt |

90| `/stickers` | Order Claude Code stickers |

91| `/tasks` | List and manage background tasks. Also available as `/bashes` |

92| `/team-onboarding` | Generate a team onboarding guide from your Claude Code usage history. Claude analyzes your sessions, commands, and MCP server usage from the past 30 days and produces a markdown guide a teammate can paste as a first message to get set up quickly |

93| `/teleport` | Pull a [Claude Code on the web](/en/claude-code-on-the-web#from-web-to-terminal) session into this terminal: opens a picker, then fetches the branch and conversation. Also available as `/tp`. Requires a claude.ai subscription |

94| `/terminal-setup` | Configure terminal keybindings for Shift+Enter and other shortcuts. Only visible in terminals that need it, like VS Code, Cursor, Windsurf, Alacritty, or Zed |

95| `/theme` | Change the color theme. Includes an `auto` option that matches your terminal's light or dark background, light and dark variants, colorblind-accessible (daltonized) themes, ANSI themes that use your terminal's color palette, and any [custom themes](/en/terminal-config#create-a-custom-theme) from `~/.claude/themes/` or plugins. Select **New custom theme…** to create one |

96| `/tui [default\|fullscreen]` | Set the terminal UI renderer and relaunch into it with your conversation intact. `fullscreen` enables the [flicker-free alt-screen renderer](/en/fullscreen). With no argument, prints the active renderer |

97| `/ultraplan <prompt>` | Draft a plan in an [ultraplan](/en/ultraplan) session, review it in your browser, then execute remotely or send it back to your terminal |

98| `/ultrareview [PR]` | Run a deep, multi-agent code review in a cloud sandbox with [ultrareview](/en/ultrareview). Includes 3 free runs on Pro and Max through May 5, 2026, then requires [extra usage](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |

99| `/upgrade` | Open the upgrade page to switch to a higher plan tier |

100| `/usage` | Show session cost, plan usage limits, and activity stats. See the [cost tracking guide](/en/costs#using-the-%2Fusage-command) for subscription-specific details. `/cost` and `/stats` are aliases |

101| `/vim` | {/* max-version: 2.1.91 */}Removed in v2.1.92. To toggle between Vim and Normal editing modes, use `/config` → Editor mode |

102| `/voice [hold\|tap\|off]` | Toggle [voice dictation](/en/voice-dictation), or enable it in a specific mode. Requires a Claude.ai account |

103| `/web-setup` | Connect your GitHub account to [Claude Code on the web](/en/web-quickstart#connect-from-your-terminal) using your local `gh` CLI credentials. `/schedule` prompts for this automatically if GitHub isn't connected |

104 

105## MCP prompts

106 

107MCP servers can expose prompts that appear as commands. These use the format `/mcp__<server>__<prompt>` and are dynamically discovered from connected servers. See [MCP prompts](/en/mcp#use-mcp-prompts-as-commands) for details.

108 

109## See also

110 

111* [Skills](/en/skills): create your own commands

112* [Interactive mode](/en/interactive-mode): keyboard shortcuts, Vim mode, and command history

113* [CLI reference](/en/cli-reference): launch-time flags

common-workflows.md +363 −202

Details

28 </Step>28 </Step>

29 29 

30 <Step title="Ask for a high-level overview">30 <Step title="Ask for a high-level overview">

31 ```31 ```text theme={null}

32 > give me an overview of this codebase 32 give me an overview of this codebase

33 ```33 ```

34 </Step>34 </Step>

35 35 

36 <Step title="Dive deeper into specific components">36 <Step title="Dive deeper into specific components">

37 ```37 ```text theme={null}

38 > explain the main architecture patterns used here 38 explain the main architecture patterns used here

39 ```39 ```

40 40 

41 ```41 ```text theme={null}

42 > what are the key data models?42 what are the key data models?

43 ```43 ```

44 44 

45 ```45 ```text theme={null}

46 > how is authentication handled?46 how is authentication handled?

47 ```47 ```

48 </Step>48 </Step>

49</Steps>49</Steps>


62 62 

63<Steps>63<Steps>

64 <Step title="Ask Claude to find relevant files">64 <Step title="Ask Claude to find relevant files">

65 ```65 ```text theme={null}

66 > find the files that handle user authentication 66 find the files that handle user authentication

67 ```67 ```

68 </Step>68 </Step>

69 69 

70 <Step title="Get context on how components interact">70 <Step title="Get context on how components interact">

71 ```71 ```text theme={null}

72 > how do these authentication files work together? 72 how do these authentication files work together?

73 ```73 ```

74 </Step>74 </Step>

75 75 

76 <Step title="Understand the execution flow">76 <Step title="Understand the execution flow">

77 ```77 ```text theme={null}

78 > trace the login process from front-end to database 78 trace the login process from front-end to database

79 ```79 ```

80 </Step>80 </Step>

81</Steps>81</Steps>


96 96 

97<Steps>97<Steps>

98 <Step title="Share the error with Claude">98 <Step title="Share the error with Claude">

99 ```99 ```text theme={null}

100 > I'm seeing an error when I run npm test 100 I'm seeing an error when I run npm test

101 ```101 ```

102 </Step>102 </Step>

103 103 

104 <Step title="Ask for fix recommendations">104 <Step title="Ask for fix recommendations">

105 ```105 ```text theme={null}

106 > suggest a few ways to fix the @ts-ignore in user.ts 106 suggest a few ways to fix the @ts-ignore in user.ts

107 ```107 ```

108 </Step>108 </Step>

109 109 

110 <Step title="Apply the fix">110 <Step title="Apply the fix">

111 ```111 ```text theme={null}

112 > update user.ts to add the null check you suggested 112 update user.ts to add the null check you suggested

113 ```113 ```

114 </Step>114 </Step>

115</Steps>115</Steps>


130 130 

131<Steps>131<Steps>

132 <Step title="Identify legacy code for refactoring">132 <Step title="Identify legacy code for refactoring">

133 ```133 ```text theme={null}

134 > find deprecated API usage in our codebase 134 find deprecated API usage in our codebase

135 ```135 ```

136 </Step>136 </Step>

137 137 

138 <Step title="Get refactoring recommendations">138 <Step title="Get refactoring recommendations">

139 ```139 ```text theme={null}

140 > suggest how to refactor utils.js to use modern JavaScript features 140 suggest how to refactor utils.js to use modern JavaScript features

141 ```141 ```

142 </Step>142 </Step>

143 143 

144 <Step title="Apply the changes safely">144 <Step title="Apply the changes safely">

145 ```145 ```text theme={null}

146 > refactor utils.js to use ES2024 features while maintaining the same behavior 146 refactor utils.js to use ES2024 features while maintaining the same behavior

147 ```147 ```

148 </Step>148 </Step>

149 149 

150 <Step title="Verify the refactoring">150 <Step title="Verify the refactoring">

151 ```151 ```text theme={null}

152 > run tests for the refactored code 152 run tests for the refactored code

153 ```153 ```

154 </Step>154 </Step>

155</Steps>155</Steps>


170 170 

171<Steps>171<Steps>

172 <Step title="View available subagents">172 <Step title="View available subagents">

173 ```173 ```text theme={null}

174 > /agents174 /agents

175 ```175 ```

176 176 

177 This shows all available subagents and lets you create new ones.177 This shows all available subagents and lets you create new ones.


180 <Step title="Use subagents automatically">180 <Step title="Use subagents automatically">

181 Claude Code automatically delegates appropriate tasks to specialized subagents:181 Claude Code automatically delegates appropriate tasks to specialized subagents:

182 182 

183 ```183 ```text theme={null}

184 > review my recent code changes for security issues184 review my recent code changes for security issues

185 ```185 ```

186 186 

187 ```187 ```text theme={null}

188 > run all tests and fix any failures188 run all tests and fix any failures

189 ```189 ```

190 </Step>190 </Step>

191 191 

192 <Step title="Explicitly request specific subagents">192 <Step title="Explicitly request specific subagents">

193 ```193 ```text theme={null}

194 > use the code-reviewer subagent to check the auth module194 use the code-reviewer subagent to check the auth module

195 ```195 ```

196 196 

197 ```197 ```text theme={null}

198 > have the debugger subagent investigate why users can't log in198 have the debugger subagent investigate why users can't log in

199 ```199 ```

200 </Step>200 </Step>

201 201 

202 <Step title="Create custom subagents for your workflow">202 <Step title="Create custom subagents for your workflow">

203 ```203 ```text theme={null}

204 > /agents204 /agents

205 ```205 ```

206 206 

207 Then select "Create New subagent" and follow the prompts to define:207 Then select "Create New subagent" and follow the prompts to define:


226 226 

227## Use Plan Mode for safe code analysis227## Use Plan Mode for safe code analysis

228 228 

229Plan Mode instructs Claude to create a plan by analyzing the codebase with read-only operations, perfect for exploring codebases, planning complex changes, or reviewing code safely. In Plan Mode, Claude uses [`AskUserQuestion`](/en/settings#tools-available-to-claude) to gather requirements and clarify your goals before proposing a plan.229Plan Mode instructs Claude to create a plan by analyzing the codebase with read-only operations, perfect for exploring codebases, planning complex changes, or reviewing code safely. In Plan Mode, Claude uses [`AskUserQuestion`](/en/tools-reference) to gather requirements and clarify your goals before proposing a plan.

230 230 

231### When to use Plan Mode231### When to use Plan Mode

232 232 


264claude --permission-mode plan264claude --permission-mode plan

265```265```

266 266 

267```267```text theme={null}

268> I need to refactor our authentication system to use OAuth2. Create a detailed migration plan.268I need to refactor our authentication system to use OAuth2. Create a detailed migration plan.

269```269```

270 270 

271Claude analyzes the current implementation and create a comprehensive plan. Refine with follow-ups:271Claude analyzes the current implementation and create a comprehensive plan. Refine with follow-ups:

272 272 

273```text theme={null}

274What about backward compatibility?

273```275```

274> What about backward compatibility?276 

275> How should we handle database migration?277```text theme={null}

278How should we handle database migration?

276```279```

277 280 

278<Tip>Press `Ctrl+G` to open the plan in your default text editor, where you can edit it directly before Claude proceeds.</Tip>281<Tip>Press `Ctrl+G` to open the plan in your default text editor, where you can edit it directly before Claude proceeds.</Tip>

279 282 

283When you accept a plan, Claude automatically names the session from the plan content. The name appears on the prompt bar and in the session picker. If you've already set a name with `--name` or `/rename`, accepting a plan won't overwrite it.

284 

280### Configure Plan Mode as default285### Configure Plan Mode as default

281 286 

282```json theme={null}287```json theme={null}


298 303 

299<Steps>304<Steps>

300 <Step title="Identify untested code">305 <Step title="Identify untested code">

301 ```306 ```text theme={null}

302 > find functions in NotificationsService.swift that are not covered by tests 307 find functions in NotificationsService.swift that are not covered by tests

303 ```308 ```

304 </Step>309 </Step>

305 310 

306 <Step title="Generate test scaffolding">311 <Step title="Generate test scaffolding">

307 ```312 ```text theme={null}

308 > add tests for the notification service 313 add tests for the notification service

309 ```314 ```

310 </Step>315 </Step>

311 316 

312 <Step title="Add meaningful test cases">317 <Step title="Add meaningful test cases">

313 ```318 ```text theme={null}

314 > add test cases for edge conditions in the notification service 319 add test cases for edge conditions in the notification service

315 ```320 ```

316 </Step>321 </Step>

317 322 

318 <Step title="Run and verify tests">323 <Step title="Run and verify tests">

319 ```324 ```text theme={null}

320 > run the new tests and fix any failures 325 run the new tests and fix any failures

321 ```326 ```

322 </Step>327 </Step>

323</Steps>328</Steps>


330 335 

331## Create pull requests336## Create pull requests

332 337 

333You can create pull requests by asking Claude directly ("create a pr for my changes") or by using the `/commit-push-pr` skill, which commits, pushes, and opens a PR in one step.338You can create pull requests by asking Claude directly ("create a pr for my changes"), or guide Claude through it step-by-step:

334 

335```

336> /commit-push-pr

337```

338 

339If you have a Slack MCP server configured and specify channels in your CLAUDE.md (for example, "post PR URLs to #team-prs"), the skill automatically posts the PR URL to those channels.

340 

341For more control over the process, guide Claude through it step-by-step or [create your own skill](/en/skills):

342 339 

343<Steps>340<Steps>

344 <Step title="Summarize your changes">341 <Step title="Summarize your changes">

345 ```342 ```text theme={null}

346 > summarize the changes I've made to the authentication module343 summarize the changes I've made to the authentication module

347 ```344 ```

348 </Step>345 </Step>

349 346 

350 <Step title="Generate a pull request">347 <Step title="Generate a pull request">

351 ```348 ```text theme={null}

352 > create a pr349 create a pr

353 ```350 ```

354 </Step>351 </Step>

355 352 

356 <Step title="Review and refine">353 <Step title="Review and refine">

357 ```354 ```text theme={null}

358 > enhance the PR description with more context about the security improvements355 enhance the PR description with more context about the security improvements

359 ```356 ```

360 </Step>357 </Step>

361</Steps>358</Steps>


372 369 

373<Steps>370<Steps>

374 <Step title="Identify undocumented code">371 <Step title="Identify undocumented code">

375 ```372 ```text theme={null}

376 > find functions without proper JSDoc comments in the auth module 373 find functions without proper JSDoc comments in the auth module

377 ```374 ```

378 </Step>375 </Step>

379 376 

380 <Step title="Generate documentation">377 <Step title="Generate documentation">

381 ```378 ```text theme={null}

382 > add JSDoc comments to the undocumented functions in auth.js 379 add JSDoc comments to the undocumented functions in auth.js

383 ```380 ```

384 </Step>381 </Step>

385 382 

386 <Step title="Review and enhance">383 <Step title="Review and enhance">

387 ```384 ```text theme={null}

388 > improve the generated documentation with more context and examples 385 improve the generated documentation with more context and examples

389 ```386 ```

390 </Step>387 </Step>

391 388 

392 <Step title="Verify documentation">389 <Step title="Verify documentation">

393 ```390 ```text theme={null}

394 > check if the documentation follows our project standards 391 check if the documentation follows our project standards

395 ```392 ```

396 </Step>393 </Step>

397</Steps>394</Steps>


406 403 

407***404***

408 405 

406## Work in notes and non-code folders

407 

408Claude Code works in any directory. Run it inside a notes vault, a documentation folder, or any collection of markdown files to search, edit, and reorganize content the same way you would code.

409 

410The `.claude/` directory and `CLAUDE.md` sit alongside other tools' config directories without conflict. Claude reads files fresh on each tool call, so it sees edits you make in another application the next time it reads that file.

411 

412***

413 

409## Work with images414## Work with images

410 415 

411Suppose you need to work with images in your codebase, and you want Claude's help analyzing image content.416Suppose you need to work with images in your codebase, and you want Claude's help analyzing image content.


420 </Step>425 </Step>

421 426 

422 <Step title="Ask Claude to analyze the image">427 <Step title="Ask Claude to analyze the image">

423 ```428 ```text theme={null}

424 > What does this image show?429 What does this image show?

425 ```430 ```

426 431 

427 ```432 ```text theme={null}

428 > Describe the UI elements in this screenshot433 Describe the UI elements in this screenshot

429 ```434 ```

430 435 

431 ```436 ```text theme={null}

432 > Are there any problematic elements in this diagram?437 Are there any problematic elements in this diagram?

433 ```438 ```

434 </Step>439 </Step>

435 440 

436 <Step title="Use images for context">441 <Step title="Use images for context">

437 ```442 ```text theme={null}

438 > Here's a screenshot of the error. What's causing it?443 Here's a screenshot of the error. What's causing it?

439 ```444 ```

440 445 

441 ```446 ```text theme={null}

442 > This is our current database schema. How should we modify it for the new feature?447 This is our current database schema. How should we modify it for the new feature?

443 ```448 ```

444 </Step>449 </Step>

445 450 

446 <Step title="Get code suggestions from visual content">451 <Step title="Get code suggestions from visual content">

447 ```452 ```text theme={null}

448 > Generate CSS to match this design mockup453 Generate CSS to match this design mockup

449 ```454 ```

450 455 

451 ```456 ```text theme={null}

452 > What HTML structure would recreate this component?457 What HTML structure would recreate this component?

453 ```458 ```

454 </Step>459 </Step>

455</Steps>460</Steps>


472 477 

473<Steps>478<Steps>

474 <Step title="Reference a single file">479 <Step title="Reference a single file">

475 ```480 ```text theme={null}

476 > Explain the logic in @src/utils/auth.js481 Explain the logic in @src/utils/auth.js

477 ```482 ```

478 483 

479 This includes the full content of the file in the conversation.484 This includes the full content of the file in the conversation.

480 </Step>485 </Step>

481 486 

482 <Step title="Reference a directory">487 <Step title="Reference a directory">

483 ```488 ```text theme={null}

484 > What's the structure of @src/components?489 What's the structure of @src/components?

485 ```490 ```

486 491 

487 This provides a directory listing with file information.492 This provides a directory listing with file information.

488 </Step>493 </Step>

489 494 

490 <Step title="Reference MCP resources">495 <Step title="Reference MCP resources">

491 ```496 ```text theme={null}

492 > Show me the data from @github:repos/owner/repo/issues497 Show me the data from @github:repos/owner/repo/issues

493 ```498 ```

494 499 

495 This fetches data from connected MCP servers using the format @server:resource. See [MCP resources](/en/mcp#use-mcp-resources) for details.500 This fetches data from connected MCP servers using the format @server:resource. See [MCP resources](/en/mcp#use-mcp-resources) for details.


509 514 

510## Use extended thinking (thinking mode)515## Use extended thinking (thinking mode)

511 516 

512[Extended thinking](https://docs.claude.com/en/docs/build-with-claude/extended-thinking) is enabled by default, reserving a portion of the output token budget (up to 31,999 tokens) for Claude to reason through complex problems step-by-step. This reasoning is visible in verbose mode, which you can toggle on with `Ctrl+O`.517[Extended thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking) is enabled by default, giving Claude space to reason through complex problems step-by-step before responding. This reasoning is visible in verbose mode, which you can toggle on with `Ctrl+O`. During extended thinking, the spinner shows inline progress hints such as "still thinking" and "almost done thinking" to indicate Claude is actively working.

518 

519Additionally, [models that support effort](/en/model-config#adjust-effort-level) use adaptive reasoning: instead of a fixed thinking token budget, the model dynamically decides whether and how much to think based on your effort level setting and the task at hand. Adaptive reasoning lets Claude respond faster to routine prompts and reserve deeper thinking for steps that benefit from it.

513 520 

514Extended thinking is particularly valuable for complex architectural decisions, challenging bugs, multi-step implementation planning, and evaluating tradeoffs between different approaches. It provides more space for exploring multiple solutions, analyzing edge cases, and self-correcting mistakes.521Extended thinking is particularly valuable for complex architectural decisions, challenging bugs, multi-step implementation planning, and evaluating tradeoffs between different approaches.

515 522 

516<Note>523<Note>

517 Phrases like "think", "think hard", "ultrathink", and "think more" are interpreted as regular prompt instructions and don't allocate thinking tokens.524 Phrases like "think", "think hard", and "think more" are interpreted as regular prompt instructions and don't allocate thinking tokens.

518</Note>525</Note>

519 526 

520### Configure thinking mode527### Configure thinking mode


522Thinking is enabled by default, but you can adjust or disable it.529Thinking is enabled by default, but you can adjust or disable it.

523 530 

524| Scope | How to configure | Details |531| Scope | How to configure | Details |

525| ---------------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |532| ------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

526| **Toggle shortcut** | Press `Option+T` (macOS) or `Alt+T` (Windows/Linux) | Toggle thinking on/off for the current session. May require [terminal configuration](/en/terminal-config) to enable Option key shortcuts |533| **Effort level** | Run `/effort`, adjust in `/model`, or set [`CLAUDE_CODE_EFFORT_LEVEL`](/en/env-vars) | Control thinking depth on [supported models](/en/model-config#adjust-effort-level) |

527| **Global default** | Use `/config` to toggle thinking mode | Sets your default across all projects.<br />Saved as `alwaysThinkingEnabled` in `~/.claude/settings.json` |534| **`ultrathink` keyword** | Include "ultrathink" anywhere in your prompt | Adds an in-context instruction telling the model to reason more on that turn. Does not change the effort level itself; see [Adjust effort level](/en/model-config#adjust-effort-level) for that |

528| **Limit token budget** | Set [`MAX_THINKING_TOKENS`](/en/settings#environment-variables) environment variable | Limit the thinking budget to a specific number of tokens. Example: `export MAX_THINKING_TOKENS=10000` |535| **Toggle shortcut** | Press `Option+T` (macOS) or `Alt+T` (Windows/Linux) | Toggle thinking on/off for the current session (all models). May require [terminal configuration](/en/terminal-config) to enable Option key shortcuts |

536| **Global default** | Use `/config` to toggle thinking mode | Sets your default across all projects (all models).<br />Saved as `alwaysThinkingEnabled` in `~/.claude/settings.json` |

537| **Limit token budget** | Set [`MAX_THINKING_TOKENS`](/en/env-vars) environment variable | Limit the thinking budget to a specific number of tokens. On models with adaptive reasoning, only `0` applies unless adaptive reasoning is disabled. Example: `export MAX_THINKING_TOKENS=10000` |

529 538 

530To view Claude's thinking process, press `Ctrl+O` to toggle verbose mode and see the internal reasoning displayed as gray italic text.539To view Claude's thinking process, press `Ctrl+O` to toggle verbose mode and see the internal reasoning displayed as gray italic text.

531 540 

532### How extended thinking token budgets work541### How extended thinking works

533 

534Extended thinking uses a **token budget** that controls how much internal reasoning Claude can perform before responding.

535 

536A larger thinking token budget provides:

537 542 

538* More space to explore multiple solution approaches step-by-step543Extended thinking controls how much internal reasoning Claude performs before responding. More thinking provides more space to explore solutions, analyze edge cases, and self-correct mistakes.

539* Room to analyze edge cases and evaluate tradeoffs thoroughly

540* Ability to revise reasoning and self-correct mistakes

541 544 

542Token budgets for thinking mode:545On [models that support effort](/en/model-config#adjust-effort-level), thinking uses adaptive reasoning: the model dynamically allocates thinking tokens based on the effort level you select. This is the recommended way to tune the tradeoff between speed and reasoning depth. If you want Claude to think more or less often than your effort level would otherwise produce, you can also say so directly in your prompt or in `CLAUDE.md`.

543 546 

544* When thinking is **enabled**, Claude can use up to **31,999 tokens** from your output budget for internal reasoning547With older models, thinking uses a fixed token budget drawn from your output allocation. The budget varies by model; see [`MAX_THINKING_TOKENS`](/en/env-vars) for per-model ceilings. You can limit the budget with that environment variable, or disable thinking entirely via `/config` or the `Option+T`/`Alt+T` toggle.

545* When thinking is **disabled** (via toggle or `/config`), Claude uses **0 tokens** for thinking

546 548 

547**Limit the thinking budget:**549On models with adaptive reasoning, `MAX_THINKING_TOKENS` only applies when set to `0` to disable thinking, or when `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1` reverts the model to the fixed budget. `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` applies to Opus 4.6 and Sonnet 4.6 only. Opus 4.7 always uses adaptive reasoning and does not support a fixed thinking budget. See [environment variables](/en/env-vars).

548 

549* Use the [`MAX_THINKING_TOKENS` environment variable](/en/settings#environment-variables) to cap the thinking budget

550* When set, this value limits the maximum tokens Claude can use for thinking

551* See the [extended thinking documentation](https://docs.claude.com/en/docs/build-with-claude/extended-thinking) for valid token ranges

552 550 

553<Warning>551<Warning>

554 You're charged for all thinking tokens used, even though Claude 4 models show summarized thinking552 You're charged for all thinking tokens used even when thinking summaries are redacted. In interactive mode, thinking appears as a collapsed stub by default. Set `showThinkingSummaries: true` in `settings.json` to show full summaries.

555</Warning>553</Warning>

556 554 

557***555***


566 564 

567From inside an active session, use `/resume` to switch to a different conversation.565From inside an active session, use `/resume` to switch to a different conversation.

568 566 

569Sessions are stored per project directory. The `/resume` picker shows sessions from the same git repository, including worktrees.567When the selected session is old and large enough that re-reading it would consume a substantial share of your usage limits, `--resume`, `--continue`, and `/resume` offer to resume from a summary instead of loading the full transcript. This prompt is not available on Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry.

568 

569Sessions are stored per project directory. By default, the `/resume` picker shows interactive sessions from the current worktree, with keyboard shortcuts to widen the list to other worktrees or projects, search, preview, and rename. Sessions started elsewhere that added the current directory with `/add-dir` are also included by default. See [Use the session picker](#use-the-session-picker) below for the full shortcut reference.

570 

571When you select a session from another worktree of the same repository, Claude Code resumes it directly without requiring you to switch directories first. Selecting a session from an unrelated project copies a `cd` and resume command to your clipboard instead.

572 

573Resuming by name resolves across the current repository and its worktrees. Both `claude --resume <name>` and `/resume <name>` look for an exact match and resume it directly, even if the session lives in a different worktree.

574 

575When the name is ambiguous, `claude --resume <name>` opens the picker with the name pre-filled as a search term. `/resume <name>` from inside a session reports an error instead, so run `/resume` with no argument to open the picker and choose.

576 

577Sessions created by `claude -p` or SDK invocations do not appear in the picker, but you can still resume one by passing its session ID directly to `claude --resume <session-id>`.

570 578 

571### Name your sessions579### Name your sessions

572 580 

573Give sessions descriptive names to find them later. This is a best practice when working on multiple tasks or features.581Give sessions descriptive names to find them later. This is a best practice when working on multiple tasks or features.

574 582 

575<Steps>583<Steps>

576 <Step title="Name the current session">584 <Step title="Name the session">

577 Use `/rename` during a session to give it a memorable name:585 Name a session at startup with `-n`:

578 586 

587 ```bash theme={null}

588 claude -n auth-refactor

579 ```589 ```

580 > /rename auth-refactor590 

591 Or use `/rename` during a session, which also shows the name on the prompt bar:

592 

593 ```text theme={null}

594 /rename auth-refactor

581 ```595 ```

582 596 

583 You can also rename any session from the picker: run `/resume`, navigate to a session, and press `R`.597 You can also rename any session from the picker: run `/resume`, navigate to a session, and press `Ctrl+R`.

584 </Step>598 </Step>

585 599 

586 <Step title="Resume by name later">600 <Step title="Resume by name later">


592 606 

593 Or from inside an active session:607 Or from inside an active session:

594 608 

595 ```609 ```text theme={null}

596 > /resume auth-refactor610 /resume auth-refactor

597 ```611 ```

598 </Step>612 </Step>

599</Steps>613</Steps>


605**Keyboard shortcuts in the picker:**619**Keyboard shortcuts in the picker:**

606 620 

607| Shortcut | Action |621| Shortcut | Action |

608| :-------- | :------------------------------------------------ |622| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------- |

609| `↑` / `↓` | Navigate between sessions |623| `↑` / `↓` | Navigate between sessions |

610| `→` / `←` | Expand or collapse grouped sessions |624| `→` / `←` | Expand or collapse grouped sessions |

611| `Enter` | Select and resume the highlighted session |625| `Enter` | Select and resume the highlighted session |

612| `P` | Preview the session content |626| `Space` | Preview the session content. `Ctrl+V` also works on terminals that do not capture it as paste |

613| `R` | Rename the highlighted session |627| `Ctrl+R` | Rename the highlighted session |

614| `/` | Search to filter sessions |628| `/` or any printable character other than `Space` | Enter search mode and filter sessions |

615| `A` | Toggle between current directory and all projects |629| `Ctrl+A` | Show sessions from all projects on this machine. Press again to restore the current repository |

616| `B` | Filter to sessions from your current git branch |630| `Ctrl+W` | Show sessions from all worktrees of the current repository. Press again to restore the current worktree. Only shown in multi-worktree repositories |

631| `Ctrl+B` | Filter to sessions from your current git branch. Press again to show sessions from all branches |

617| `Esc` | Exit the picker or search mode |632| `Esc` | Exit the picker or search mode |

618 633 

619**Session organization:**634**Session organization:**

620 635 

621The picker displays sessions with helpful metadata:636The picker displays sessions with helpful metadata:

622 637 

623* Session name or initial prompt638* Session name if set, otherwise the conversation summary or first user prompt

624* Time elapsed since last activity639* Time elapsed since last activity

625* Message count640* Message count

626* Git branch (if applicable)641* Git branch (if applicable)

642* Project path, shown after widening to all projects with `Ctrl+A`

627 643 

628Forked sessions (created with `/rewind` or `--fork-session`) are grouped together under their root session, making it easier to find related conversations.644Forked sessions (created with `/branch`, `/rewind`, or `--fork-session`) are grouped together under their root session, making it easier to find related conversations.

629 645 

630<Tip>646<Tip>

631 Tips:647 Tips:

632 648 

633 * **Name sessions early**: Use `/rename` when starting work on a distinct taskit's much easier to find "payment-integration" than "explain this function" later649 * **Name sessions early**: Use `/rename` when starting work on a distinct task: it's much easier to find "payment-integration" than "explain this function" later

634 * Use `--continue` for quick access to your most recent conversation in the current directory650 * Use `--continue` for quick access to your most recent conversation in the current directory

635 * Use `--resume session-name` when you know which session you need651 * Use `--resume session-name` when you know which session you need

636 * Use `--resume` (without a name) when you need to browse and select652 * Use `--resume` (without a name) when you need to browse and select

637 * For scripts, use `claude --continue --print "prompt"` to resume in non-interactive mode653 * For scripts, use `claude --continue --print "prompt"` to resume in non-interactive mode

638 * Press `P` in the picker to preview a session before resuming it654 * Press `Space` in the picker to preview a session before resuming it

639 * The resumed conversation starts with the same model and configuration as the original655 * The resumed conversation starts with the same model and configuration as the original

640 656 

641 How it works:657 How it works:


650 666 

651## Run parallel Claude Code sessions with Git worktrees667## Run parallel Claude Code sessions with Git worktrees

652 668 

653Suppose you need to work on multiple tasks simultaneously with complete code isolation between Claude Code instances.669When working on multiple tasks at once, you need each Claude session to have its own copy of the codebase so changes don't collide. Git worktrees solve this by creating separate working directories that each have their own files and branch, while sharing the same repository history and remote connections. This means you can have Claude working on a feature in one worktree while fixing a bug in another, without either session interfering with the other.

654 670 

655<Steps>671Use the `--worktree` (`-w`) flag to create an isolated worktree and start Claude in it. The value you pass becomes the worktree directory name and branch name:

656 <Step title="Understand Git worktrees">

657 Git worktrees allow you to check out multiple branches from the same

658 repository into separate directories. Each worktree has its own working

659 directory with isolated files, while sharing the same Git history. Learn

660 more in the [official Git worktree

661 documentation](https://git-scm.com/docs/git-worktree).

662 </Step>

663 672 

664 <Step title="Create a new worktree">673```bash theme={null}

665 ```bash theme={null}674# Start Claude in a worktree named "feature-auth"

666 # Create a new worktree with a new branch 675# Creates .claude/worktrees/feature-auth/ with a new branch

667 git worktree add ../project-feature-a -b feature-a676claude --worktree feature-auth

668 677 

669 # Or create a worktree with an existing branch678# Start another session in a separate worktree

670 git worktree add ../project-bugfix bugfix-123679claude --worktree bugfix-123

671 ```680```

672 681 

673 This creates a new directory with a separate working copy of your repository.682If you omit the name, Claude generates a random one automatically:

674 </Step>

675 683 

676 <Step title="Run Claude Code in each worktree">684```bash theme={null}

677 ```bash theme={null}685# Auto-generates a name like "bright-running-fox"

678 # Navigate to your worktree 686claude --worktree

679 cd ../project-feature-a687```

680 688 

681 # Run Claude Code in this isolated environment689Worktrees are created at `<repo>/.claude/worktrees/<name>` and branch from the default remote branch, which is where `origin/HEAD` points. The worktree branch is named `worktree-<name>`.

682 claude

683 ```

684 </Step>

685 690 

686 <Step title="Run Claude in another worktree">691The base branch is not configurable through a Claude Code flag or setting. `origin/HEAD` is a reference stored in your local `.git` directory that Git set once when you cloned. If the repository's default branch later changes on GitHub or GitLab, your local `origin/HEAD` keeps pointing at the old one, and worktrees will branch from there. To re-sync your local reference with whatever the remote currently considers its default:

687 ```bash theme={null}692 

688 cd ../project-bugfix693```bash theme={null}

689 claude694git remote set-head origin -a

695```

696 

697This is a standard Git command that only updates your local `.git` directory. Nothing on the remote server changes. If you want worktrees to base off a specific branch rather than the remote's default, set it explicitly with `git remote set-head origin your-branch-name`.

698 

699For full control over how worktrees are created, including choosing a different base per invocation, configure a [WorktreeCreate hook](/en/hooks#worktreecreate). The hook replaces Claude Code's default `git worktree` logic entirely, so you can fetch and branch from whatever ref you need.

700 

701You can also ask Claude to "work in a worktree" or "start a worktree" during a session, and it will create one automatically.

702 

703### Subagent worktrees

704 

705Subagents can also use worktree isolation to work in parallel without conflicts. Ask Claude to "use worktrees for your agents" or configure it in a [custom subagent](/en/sub-agents#supported-frontmatter-fields) by adding `isolation: worktree` to the agent's frontmatter. Each subagent gets its own worktree that is automatically cleaned up when the subagent finishes without changes.

706 

707### Worktree cleanup

708 

709When you exit a worktree session, Claude handles cleanup based on whether you made changes:

710 

711* **No changes**: the worktree and its branch are removed automatically

712* **Changes or commits exist**: Claude prompts you to keep or remove the worktree. Keeping preserves the directory and branch so you can return later. Removing deletes the worktree directory and its branch, discarding all uncommitted changes and commits

713 

714Subagent worktrees orphaned by a crash or an interrupted parallel run are removed automatically at startup once they are older than your [`cleanupPeriodDays`](/en/settings#available-settings) setting, provided they have no uncommitted changes, no untracked files, and no unpushed commits. Worktrees you create with `--worktree` are never removed by this sweep.

715 

716To clean up worktrees outside of a Claude session, use [manual worktree management](#manage-worktrees-manually).

717 

718<Tip>

719 Add `.claude/worktrees/` to your `.gitignore` to prevent worktree contents from appearing as untracked files in your main repository.

720</Tip>

721 

722### Copy gitignored files to worktrees

723 

724Git worktrees are fresh checkouts, so they don't include untracked files like `.env` or `.env.local` from your main repository. To automatically copy these files when Claude creates a worktree, add a `.worktreeinclude` file to your project root.

725 

726The file uses `.gitignore` syntax to list which files to copy. Only files that match a pattern and are also gitignored get copied, so tracked files are never duplicated.

727 

728```text .worktreeinclude theme={null}

729.env

730.env.local

731config/secrets.json

732```

733 

734This applies to worktrees created with `--worktree`, subagent worktrees, and parallel sessions in the [desktop app](/en/desktop#work-in-parallel-with-sessions).

735 

736### Manage worktrees manually

737 

738For more control over worktree location and branch configuration, create worktrees with Git directly. This is useful when you need to check out a specific existing branch or place the worktree outside the repository.

739 

740```bash theme={null}

741# Create a worktree with a new branch

742git worktree add ../project-feature-a -b feature-a

743 

744# Create a worktree with an existing branch

745git worktree add ../project-bugfix bugfix-123

746 

747# Start Claude in the worktree

748cd ../project-feature-a && claude

749 

750# Clean up when done

751git worktree list

752git worktree remove ../project-feature-a

753```

754 

755Learn more in the [official Git worktree documentation](https://git-scm.com/docs/git-worktree).

756 

757<Tip>

758 Remember to initialize your development environment in each new worktree according to your project's setup. Depending on your stack, this might include running dependency installation (`npm install`, `yarn`), setting up virtual environments, or following your project's standard setup process.

759</Tip>

760 

761### Non-git version control

762 

763Worktree isolation works with git by default. For other version control systems like SVN, Perforce, or Mercurial, configure [WorktreeCreate and WorktreeRemove hooks](/en/hooks#worktreecreate) to provide custom worktree creation and cleanup logic. When configured, these hooks replace the default git behavior when you use `--worktree`, so [`.worktreeinclude`](#copy-gitignored-files-to-worktrees) is not processed. Copy any local configuration files inside your hook script instead.

764 

765For automated coordination of parallel sessions with shared tasks and messaging, see [agent teams](/en/agent-teams).

766 

767***

768 

769## Get notified when Claude needs your attention

770 

771When you kick off a long-running task and switch to another window, you can set up desktop notifications so you know when Claude finishes or needs your input. This uses the `Notification` [hook event](/en/hooks-guide#get-notified-when-claude-needs-input), which fires whenever Claude is waiting for permission, idle and ready for a new prompt, or completing authentication.

772 

773<Steps>

774 <Step title="Add the hook to your settings">

775 Open `~/.claude/settings.json` and add a `Notification` hook that calls your platform's native notification command:

776 

777 <Tabs>

778 <Tab title="macOS">

779 ```json theme={null}

780 {

781 "hooks": {

782 "Notification": [

783 {

784 "matcher": "",

785 "hooks": [

786 {

787 "type": "command",

788 "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"

789 }

790 ]

791 }

792 ]

793 }

794 }

795 ```

796 </Tab>

797 

798 <Tab title="Linux">

799 ```json theme={null}

800 {

801 "hooks": {

802 "Notification": [

803 {

804 "matcher": "",

805 "hooks": [

806 {

807 "type": "command",

808 "command": "notify-send 'Claude Code' 'Claude Code needs your attention'"

809 }

810 ]

811 }

812 ]

813 }

814 }

815 ```

816 </Tab>

817 

818 <Tab title="Windows">

819 ```json theme={null}

820 {

821 "hooks": {

822 "Notification": [

823 {

824 "matcher": "",

825 "hooks": [

826 {

827 "type": "command",

828 "command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""

829 }

830 ]

831 }

832 ]

833 }

834 }

690 ```835 ```

836 </Tab>

837 </Tabs>

838 

839 If your settings file already has a `hooks` key, merge the `Notification` entry into it rather than overwriting. You can also ask Claude to write the hook for you by describing what you want in the CLI.

691 </Step>840 </Step>

692 841 

693 <Step title="Manage your worktrees">842 <Step title="Optionally narrow the matcher">

694 ```bash theme={null}843 By default the hook fires on all notification types. To fire only for specific events, set the `matcher` field to one of these values:

695 # List all worktrees

696 git worktree list

697 844 

698 # Remove a worktree when done845 | Matcher | Fires when |

699 git worktree remove ../project-feature-a846 | :------------------- | :---------------------------------------------- |

700 ```847 | `permission_prompt` | Claude needs you to approve a tool use |

848 | `idle_prompt` | Claude is done and waiting for your next prompt |

849 | `auth_success` | Authentication completes |

850 | `elicitation_dialog` | Claude is asking you a question |

701 </Step>851 </Step>

702</Steps>

703 852 

704<Tip>853 <Step title="Verify the hook">

705 Tips:854 Type `/hooks` and select `Notification` to confirm the hook appears. Selecting it shows the command that will run. To test it end-to-end, ask Claude to run a command that requires permission and switch away from the terminal, or ask Claude to trigger a notification directly.

855 </Step>

856</Steps>

706 857 

707 * Each worktree has its own independent file state, making it perfect for parallel Claude Code sessions858For the complete event schema and notification types, see the [Notification reference](/en/hooks#notification).

708 * Changes made in one worktree won't affect others, preventing Claude instances from interfering with each other

709 * All worktrees share the same Git history and remote connections

710 * For long-running tasks, you can have Claude working in one worktree while you continue development in another

711 * Use descriptive directory names to easily identify which task each worktree is for

712 * Remember to initialize your development environment in each new worktree according to your project's setup. Depending on your stack, this might include:

713 * JavaScript projects: Running dependency installation (`npm install`, `yarn`)

714 * Python projects: Setting up virtual environments or installing with package managers

715 * Other languages: Following your project's standard setup process

716</Tip>

717 859 

718***860***

719 861 


759 901 

760 * Use pipes to integrate Claude into existing shell scripts902 * Use pipes to integrate Claude into existing shell scripts

761 * Combine with other Unix tools for powerful workflows903 * Combine with other Unix tools for powerful workflows

762 * Consider using --output-format for structured output904 * Consider using `--output-format` for structured output

763</Tip>905</Tip>

764 906 

765### Control output format907### Control output format


802 944 

803***945***

804 946 

947## Run Claude on a schedule

948 

949Suppose you want Claude to handle a task automatically on a recurring basis, like reviewing open PRs every morning, auditing dependencies weekly, or checking for CI failures overnight.

950 

951Pick a scheduling option based on where you want the task to run:

952 

953| Option | Where it runs | Best for |

954| :----------------------------------------------------- | :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

955| [Routines](/en/routines) | Anthropic-managed infrastructure | Tasks that should run even when your computer is off. Can also trigger on API calls or GitHub events in addition to a schedule. Configure at [claude.ai/code/routines](https://claude.ai/code/routines). |

956| [Desktop scheduled tasks](/en/desktop-scheduled-tasks) | Your machine, via the desktop app | Tasks that need direct access to local files, tools, or uncommitted changes. |

957| [GitHub Actions](/en/github-actions) | Your CI pipeline | Tasks tied to repo events like opened PRs, or cron schedules that should live alongside your workflow config. |

958| [`/loop`](/en/scheduled-tasks) | The current CLI session | Quick polling while a session is open. Tasks stop when you start a new conversation; `--resume` and `--continue` restore unexpired ones. |

959 

960<Tip>

961 When writing prompts for scheduled tasks, be explicit about what success looks like and what to do with results. The task runs autonomously, so it can't ask clarifying questions. For example: "Review open PRs labeled `needs-review`, leave inline comments on any issues, and post a summary in the `#eng-reviews` Slack channel."

962</Tip>

963 

964***

965 

805## Ask Claude about its capabilities966## Ask Claude about its capabilities

806 967 

807Claude has built-in access to its documentation and can answer questions about its own features and limitations.968Claude has built-in access to its documentation and can answer questions about its own features and limitations.

808 969 

809### Example questions970### Example questions

810 971 

811```972```text theme={null}

812> can Claude Code create pull requests?973can Claude Code create pull requests?

813```974```

814 975 

815```976```text theme={null}

816> how does Claude Code handle permissions?977how does Claude Code handle permissions?

817```978```

818 979 

819```980```text theme={null}

820> what skills are available?981what skills are available?

821```982```

822 983 

823```984```text theme={null}

824> how do I use MCP with Claude Code?985how do I use MCP with Claude Code?

825```986```

826 987 

827```988```text theme={null}

828> how do I configure Claude Code for Amazon Bedrock?989how do I configure Claude Code for Amazon Bedrock?

829```990```

830 991 

831```992```text theme={null}

832> what are the limitations of Claude Code?993what are the limitations of Claude Code?

833```994```

834 995 

835<Note>996<Note>

836 Claude provides documentation-based answers to these questions. For executable examples and hands-on demonstrations, refer to the specific workflow sections above.997 Claude provides documentation-based answers to these questions. For hands-on demonstrations, run `/powerup` for interactive lessons with animated demos, or refer to the specific workflow sections above.

837</Note>998</Note>

838 999 

839<Tip>1000<Tip>


862 </Card>1023 </Card>

863 1024 

864 <Card title="Reference implementation" icon="code" href="https://github.com/anthropics/claude-code/tree/main/.devcontainer">1025 <Card title="Reference implementation" icon="code" href="https://github.com/anthropics/claude-code/tree/main/.devcontainer">

865 Clone our development container reference implementation1026 Clone the development container reference implementation

866 </Card>1027 </Card>

867</CardGroup>1028</CardGroup>

computer-use.md +214 −0 added

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# Let Claude use your computer from the CLI

6 

7> Enable computer use in the Claude Code CLI so Claude can open apps, click, type, and see your screen on macOS. Test native apps, debug visual issues, and automate GUI-only tools without leaving your terminal.

8 

9<Note>

10 {/* plan-availability: feature=computer-use plans=pro,max */}

11 

12 Computer use is a research preview on macOS that requires a Pro or Max plan. It is not available on Team or Enterprise plans. It requires Claude Code v2.1.85 or later and an interactive session, so it is not available in non-interactive mode with the `-p` flag.

13</Note>

14 

15Computer use lets Claude open apps, control your screen, and work on your machine the way you would. From the CLI, Claude can compile a Swift app, launch it, click through every button, and screenshot the result, all in the same conversation where it wrote the code.

16 

17This page covers how computer use works in the CLI. For the Desktop app on macOS or Windows, see [computer use in Desktop](/en/desktop#let-claude-use-your-computer).

18 

19## What you can do with computer use

20 

21Computer use handles tasks that require a GUI: anything you'd normally have to leave the terminal and do by hand.

22 

23* **Build and validate native apps**: ask Claude to build a macOS menu bar app. Claude writes the Swift, compiles it, launches it, and clicks through every control to verify it works before you ever open it.

24* **End-to-end UI testing**: point Claude at a local Electron app and say "test the onboarding flow." Claude opens the app, clicks through signup, and screenshots each step. No Playwright config, no test harness.

25* **Debug visual and layout issues**: tell Claude "the modal is clipping on small windows." Claude resizes the window, reproduces the bug, screenshots it, patches the CSS, and verifies the fix. Claude sees what you see.

26* **Drive GUI-only tools**: interact with design tools, hardware control panels, the iOS Simulator, or proprietary apps that have no CLI or API.

27 

28## When computer use applies

29 

30Claude has several ways to interact with an app or service. Computer use is the broadest and slowest, so Claude tries the most precise tool first:

31 

32* If you have an [MCP server](/en/mcp) for the service, Claude uses that.

33* If the task is a shell command, Claude uses Bash.

34* If the task is browser work and you have [Claude in Chrome](/en/chrome) set up, Claude uses that.

35* If none of those apply, Claude uses computer use.

36 

37Screen control is reserved for things nothing else can reach: native apps, simulators, and tools without an API.

38 

39## Enable computer use

40 

41Computer use is available as a built-in MCP server called `computer-use`. It's off by default until you enable it.

42 

43<Steps>

44 <Step title="Open the MCP menu">

45 In an interactive Claude Code session, run:

46 

47 ```text theme={null}

48 /mcp

49 ```

50 

51 Find `computer-use` in the server list. It shows as disabled.

52 </Step>

53 

54 <Step title="Enable the server">

55 Select `computer-use` and choose **Enable**. The setting persists per project, so you only do this once for each project where you want computer use.

56 </Step>

57 

58 <Step title="Grant macOS permissions">

59 The first time Claude tries to use your computer, you'll see a prompt to grant two macOS permissions:

60 

61 * **Accessibility**: lets Claude click, type, and scroll

62 * **Screen Recording**: lets Claude see what's on your screen

63 

64 The prompt includes links to open the relevant System Settings pane. Grant both, then select **Try again** in the prompt. macOS may require you to restart Claude Code after granting Screen Recording.

65 </Step>

66</Steps>

67 

68After setup, ask Claude to do something that needs the GUI:

69 

70```text theme={null}

71Build the app target, launch it, and click through each tab to make

72sure nothing crashes. Screenshot any error states you find.

73```

74 

75## Approve apps per session

76 

77Enabling the `computer-use` server doesn't grant Claude access to every app on your machine. The first time Claude needs a specific app in a session, a prompt appears in your terminal showing:

78 

79* Which apps Claude wants to control

80* Any extra permissions requested, such as clipboard access

81* How many other apps will be hidden while Claude works

82 

83Choose **Allow for this session** or **Deny**. Approvals last for the current session. You can approve multiple apps at once when Claude requests them together.

84 

85Apps with broad reach show an extra warning in the prompt so you know what approving them grants:

86 

87| Warning | Applies to |

88| :------------------------- | :----------------------------------------------------------- |

89| Equivalent to shell access | Terminal, iTerm, VS Code, Warp, and other terminals and IDEs |

90| Can read or write any file | Finder |

91| Can change system settings | System Settings |

92 

93These apps aren't blocked. The warning lets you decide whether the task warrants that level of access.

94 

95Claude's level of control also varies by app category: browsers and trading platforms are view-only, terminals and IDEs are click-only, and everything else gets full control. See [app permissions in Desktop](/en/desktop#app-permissions) for the complete tier breakdown.

96 

97## How Claude works on your screen

98 

99Understanding the flow helps you anticipate what Claude will do and how to intervene.

100 

101### One session at a time

102 

103Computer use holds a machine-wide lock while active. If another Claude Code session is already using your computer, new attempts fail with a message telling you which session holds the lock. Finish or exit that session first.

104 

105### Apps are hidden while Claude works

106 

107When Claude starts controlling your screen, other visible apps are hidden so Claude interacts with only the approved apps. Your terminal window stays visible and is excluded from screenshots, so you can watch the session and Claude never sees its own output.

108 

109When Claude finishes the turn, hidden apps are restored automatically.

110 

111### Screenshots are downscaled automatically

112 

113Claude Code downscales every screenshot before sending it to the model. You don't need to lower your display resolution or resize windows on Retina or other high-resolution displays. A 16-inch MacBook Pro at native Retina resolution captures at 3456×2234 and downscales to roughly 1372×887, preserving aspect ratio.

114 

115There is no setting to change the target size. If on-screen text or controls are too small for Claude to read after downscaling, increase their size in the app rather than changing your display resolution.

116 

117### Stop at any time

118 

119When Claude acquires the lock, a macOS notification appears: "Claude is using your computer · press Esc to stop." Press `Esc` anywhere to abort the current action immediately, or press `Ctrl+C` in the terminal. Either way, Claude releases the lock, unhides your apps, and returns control to you.

120 

121A second notification appears when Claude is done.

122 

123## Safety and the trust boundary

124 

125<Warning>

126 Unlike the [sandboxed Bash tool](/en/sandboxing), computer use runs on your actual desktop with access to the apps you approve. Claude checks each action and flags potential prompt injection from on-screen content, but the trust boundary is different. See the [computer use safety guide](https://support.claude.com/en/articles/14128542) for best practices.

127</Warning>

128 

129The built-in guardrails reduce risk without requiring configuration:

130 

131* **Per-app approval**: Claude can only control apps you've approved in the current session.

132* **Sentinel warnings**: apps that grant shell, filesystem, or system settings access are flagged before you approve.

133* **Terminal excluded from screenshots**: Claude never sees your terminal window, so on-screen prompts in your session can't feed back into the model.

134* **Global escape**: the `Esc` key aborts computer use from anywhere, and the key press is consumed so prompt injection can't use it to dismiss dialogs.

135* **Lock file**: only one session can control your machine at a time.

136 

137## Example workflows

138 

139These examples show common ways to combine computer use with coding tasks.

140 

141### Validate a native build

142 

143After making changes to a macOS or iOS app, have Claude compile and verify in one pass:

144 

145```text theme={null}

146Build the MenuBarStats target, launch it, open the preferences window,

147and verify the interval slider updates the label. Screenshot the

148preferences window when you're done.

149```

150 

151Claude runs `xcodebuild`, launches the app, interacts with the UI, and reports what it finds.

152 

153### Reproduce a layout bug

154 

155When a visual bug only appears at certain window sizes, let Claude find it:

156 

157```text theme={null}

158The settings modal clips its footer on narrow windows. Resize the app

159window down until you can reproduce it, screenshot the clipped state,

160then check the CSS for the modal container.

161```

162 

163Claude resizes the window, captures the broken state, and reads the relevant stylesheets.

164 

165### Test a simulator flow

166 

167Drive the iOS Simulator without writing XCTest:

168 

169```text theme={null}

170Open the iOS Simulator, launch the app, tap through the onboarding

171screens, and tell me if any screen takes more than a second to load.

172```

173 

174Claude controls the simulator the same way you would with a mouse.

175 

176## Differences from the Desktop app

177 

178The CLI and Desktop surfaces share the same computer use engine, with a few differences:

179 

180| Feature | Desktop | CLI |

181| :------------------- | :------------------------------------------------------- | :------------------------------ |

182| Platforms | macOS and Windows | macOS only |

183| Enable | Toggle in **Settings > General** (under **Desktop app**) | Enable `computer-use` in `/mcp` |

184| Denied apps list | Configurable in Settings | Not yet available |

185| Auto-unhide toggle | Optional | Always on |

186| Dispatch integration | Dispatch-spawned sessions can use computer use | Not applicable |

187 

188## Troubleshooting

189 

190### "Computer use is in use by another Claude session"

191 

192Another Claude Code session holds the lock. Finish the task in that session or exit it. If the other session crashed, the lock is released automatically when Claude detects the process is no longer running.

193 

194### macOS permissions prompt keeps reappearing

195 

196macOS sometimes requires a restart of the requesting process after you grant Screen Recording. Quit Claude Code completely and start a new session. If the prompt persists, open **System Settings > Privacy & Security > Screen Recording** and confirm your terminal app is listed and enabled.

197 

198### `computer-use` doesn't appear in `/mcp`

199 

200The server only appears on eligible setups. Check that:

201 

202* You're on macOS. Computer use in the CLI is not available on Linux or Windows. On Windows, use [computer use in Desktop](/en/desktop#let-claude-use-your-computer) instead.

203* You're running Claude Code v2.1.85 or later. Run `claude --version` to check.

204* You're on a Pro or Max plan. Run `/status` to confirm your subscription.

205* You're authenticated through claude.ai. Computer use is not available with third-party providers like Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. If you access Claude exclusively through a third-party provider, you need a separate claude.ai account to use this feature.

206* You're in an interactive session. Computer use is not available in non-interactive mode with the `-p` flag.

207 

208## See also

209 

210* [Computer use in Desktop](/en/desktop#let-claude-use-your-computer): the same capability with a graphical settings page

211* [Claude in Chrome](/en/chrome): browser automation for web-based tasks

212* [MCP](/en/mcp): connect Claude to structured tools and APIs

213* [Sandboxing](/en/sandboxing): how Claude's Bash tool isolates filesystem and network access

214* [Computer use safety guide](https://support.claude.com/en/articles/14128542): best practices for safe computer use

context-window.md +53 −0 added

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# Explore the context window

6 

7> An interactive simulation of how Claude Code's context window fills during a session. See what loads automatically, what each file read costs, and when rules and hooks fire.

8 

9 

10Claude Code's context window holds everything Claude knows about your session: your instructions, the files it reads, its own responses, and content that never appears in your terminal. The timeline below walks through what loads and when. See [the written breakdown](#what-the-timeline-shows) for the same content as a list.

11 

12<ContextWindow />

13 

14## What the timeline shows

15 

16The session walks through a realistic flow with representative token counts:

17 

18* **Before you type anything**: CLAUDE.md, auto memory, MCP tool names, and skill descriptions all load into context. Your own setup may add more here, like an [output style](/en/output-styles) or text from [`--append-system-prompt`](/en/cli-reference), which both go into the system prompt the same way.

19* **As Claude works**: each file read adds to context, [path-scoped rules](/en/memory#path-specific-rules) load automatically alongside matching files, and a [PostToolUse hook](/en/hooks-guide) fires after each edit.

20* **The follow-up prompt**: a [subagent](/en/sub-agents) handles the research in its own separate context window, so the large file reads stay out of yours. Only the summary and a small metadata trailer come back.

21* **At the end**: `/compact` replaces the conversation with a structured summary. Most startup content reloads automatically; the table below shows what happens to each mechanism.

22 

23## What survives compaction

24 

25When a long session compacts, Claude Code summarizes the conversation history to fit the context window. What happens to your instructions depends on how they were loaded:

26 

27| Mechanism | After compaction |

28| :---------------------------------------- | :------------------------------------------------------------------------------------------ |

29| System prompt and output style | Unchanged; not part of message history |

30| Project-root CLAUDE.md and unscoped rules | Re-injected from disk |

31| Auto memory | Re-injected from disk |

32| Rules with `paths:` frontmatter | Lost until a matching file is read again |

33| Nested CLAUDE.md in subdirectories | Lost until a file in that subdirectory is read again |

34| Invoked skill bodies | Re-injected, capped at 5,000 tokens per skill and 25,000 tokens total; oldest dropped first |

35| Hooks | Not applicable; hooks run as code, not context |

36 

37Path-scoped rules and nested CLAUDE.md files load into message history when their trigger file is read, so compaction summarizes them away with everything else. They reload the next time Claude reads a matching file. If a rule must persist across compaction, drop the `paths:` frontmatter or move it to the project-root CLAUDE.md.

38 

39Skill bodies are re-injected after compaction, but large skills are truncated to fit the per-skill cap, and the oldest invoked skills are dropped once the total budget is exceeded. Truncation keeps the start of the file, so put the most important instructions near the top of `SKILL.md`.

40 

41## Check your own session

42 

43The visualization uses representative numbers. To see your actual context usage at any point, run `/context` for a live breakdown by category with optimization suggestions. Run `/memory` to check which CLAUDE.md and auto memory files loaded at startup.

44 

45## Related resources

46 

47For deeper coverage of the features shown in the timeline, see these pages:

48 

49* [Extend Claude Code](/en/features-overview): when to use CLAUDE.md vs skills vs rules vs hooks vs MCP

50* [Store instructions and memories](/en/memory): CLAUDE.md hierarchy and auto memory

51* [Subagents](/en/sub-agents): delegate research to a separate context window

52* [Best practices](/en/best-practices): managing context as your primary constraint

53* [Reduce token usage](/en/costs#reduce-token-usage): strategies for keeping context usage low

costs.md +33 −16

Details

6 6 

7> Track token usage, set team spend limits, and reduce Claude Code costs with context management, model selection, extended thinking settings, and preprocessing hooks.7> Track token usage, set team spend limits, and reduce Claude Code costs with context management, model selection, extended thinking settings, and preprocessing hooks.

8 8 

9Claude Code consumes tokens for each interaction. Costs vary based on codebase size, query complexity, and conversation length. The average cost is \$6 per developer per day, with daily costs remaining below \$12 for 90% of users.9Claude Code charges by API token consumption. For subscription plan pricing (Pro, Max, Team, Enterprise), see [claude.com/pricing](https://claude.com/pricing). Per-developer costs vary widely based on model selection, codebase size, and usage patterns such as running multiple instances or automation.

10 10 

11For team usage, Claude Code charges by API token consumption. On average, Claude Code costs \~\$100-200/developer per month with Sonnet 4.5 though there is large variance depending on how many instances users are running and whether they're using it in automation.11Across enterprise deployments, the average cost is around \$13 per developer per active day and \$150-250 per developer per month, with costs remaining below \$30 per active day for 90% of users. To estimate spend for your own team, start with a small pilot group and use the tracking tools below to establish a baseline before wider rollout.

12 12 

13This page covers how to [track your costs](#track-your-costs), [manage costs for teams](#managing-costs-for-teams), and [reduce token usage](#reduce-token-usage).13This page covers how to [track your costs](#track-your-costs), [manage costs for teams](#managing-costs-for-teams), and [reduce token usage](#reduce-token-usage).

14 14 

15## Track your costs15## Track your costs

16 16 

17### Using the `/cost` command17### Using the `/usage` command

18 18 

19<Note>19<Note>

20 The `/cost` command shows API token usage and is intended for API users. Claude Max and Pro subscribers have usage included in their subscription, so `/cost` data isn't relevant for billing purposes. Subscribers can use `/stats` to view usage patterns.20 The Session block in `/usage` shows API token usage and is intended for API users. Claude Max and Pro subscribers have usage included in their subscription, so the session cost figure isn't relevant for billing purposes. Subscribers see plan usage bars and activity stats on the same screen.

21</Note>21</Note>

22 22 

23The `/cost` command provides detailed token usage statistics for your current session:23The `/usage` command provides detailed token usage statistics for your current session. The dollar figure is an estimate computed locally from token counts and may differ from your actual bill. For authoritative billing, see the Usage page in the [Claude Console](https://platform.claude.com/usage).

24 24 

25```25```text theme={null}

26Total cost: $0.5526Total cost: $0.55

27Total duration (API): 6m 19.7s27Total duration (API): 6m 19.7s

28Total duration (wall): 6h 33m 10.2s28Total duration (wall): 6h 33m 10.2s


35 35 

36<Note>36<Note>

37 When you first authenticate Claude Code with your Claude Console account, a workspace called "Claude Code" is automatically created for you. This workspace provides centralized cost tracking and management for all Claude Code usage in your organization. You cannot create API keys for this workspace; it is exclusively for Claude Code authentication and usage.37 When you first authenticate Claude Code with your Claude Console account, a workspace called "Claude Code" is automatically created for you. This workspace provides centralized cost tracking and management for all Claude Code usage in your organization. You cannot create API keys for this workspace; it is exclusively for Claude Code authentication and usage.

38 

39 For organizations with custom rate limits, Claude Code traffic in this workspace counts toward your organization's overall API rate limits. You can set a [workspace rate limit](https://platform.claude.com/docs/en/api/rate-limits#setting-lower-limits-for-workspaces) on this workspace's Limits page in the Claude Console to cap Claude Code's share and protect other production workloads.

38</Note>40</Note>

39 41 

40On Bedrock, Vertex, and Foundry, Claude Code does not send metrics from your cloud. To get cost metrics, several large enterprises reported using [LiteLLM](/en/llm-gateway#litellm-configuration), which is an open-source tool that helps companies [track spend by key](https://docs.litellm.ai/docs/proxy/virtual_keys#tracking-spend). This project is unaffiliated with Anthropic and we have not audited its security.42On Bedrock, Vertex, and Foundry, Claude Code does not send metrics from your cloud. To get cost metrics, several large enterprises reported using [LiteLLM](/en/llm-gateway#litellm-configuration), which is an open-source tool that helps companies [track spend by key](https://docs.litellm.ai/docs/proxy/virtual_keys#tracking-spend). This project is unaffiliated with Anthropic and has not been audited for security.

41 43 

42### Rate limit recommendations44### Rate limit recommendations

43 45 


54 56 

55For example, if you have 200 users, you might request 20k TPM for each user, or 4 million total TPM (200\*20,000 = 4 million).57For example, if you have 200 users, you might request 20k TPM for each user, or 4 million total TPM (200\*20,000 = 4 million).

56 58 

57The TPM per user decreases as team size grows because we expect fewer users to use Claude Code concurrently in larger organizations. These rate limits apply at the organization level, not per individual user, which means individual users can temporarily consume more than their calculated share when others aren't actively using the service.59The TPM per user decreases as team size grows because fewer users tend to use Claude Code concurrently in larger organizations. These rate limits apply at the organization level, not per individual user, which means individual users can temporarily consume more than their calculated share when others aren't actively using the service.

58 60 

59<Note>61<Note>

60 If you anticipate scenarios with unusually high concurrent usage (such as live training sessions with large groups), you may need higher TPM allocations per user.62 If you anticipate scenarios with unusually high concurrent usage (such as live training sessions with large groups), you may need higher TPM allocations per user.

61</Note>63</Note>

62 64 

65### Agent team token costs

66 

67[Agent teams](/en/agent-teams) spawn multiple Claude Code instances, each with its own context window. Token usage scales with the number of active teammates and how long each one runs.

68 

69To keep agent team costs manageable:

70 

71* Use Sonnet for teammates. It balances capability and cost for coordination tasks.

72* Keep teams small. Each teammate runs its own context window, so token usage is roughly proportional to team size.

73* Keep spawn prompts focused. Teammates load CLAUDE.md, MCP servers, and skills automatically, but everything in the spawn prompt adds to their context from the start.

74* Clean up teams when work is done. Active teammates continue consuming tokens even if idle.

75* Agent teams are disabled by default. Set `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` in your [settings.json](/en/settings) or environment to enable them. See [enable agent teams](/en/agent-teams#enable-agent-teams).

76 

63## Reduce token usage77## Reduce token usage

64 78 

65Token costs scale with context size: the more context Claude processes, the more tokens you use. Claude Code automatically optimizes costs through prompt caching (which reduces costs for repeated content like system prompts) and auto-compaction (which summarizes conversation history when approaching context limits).79Token costs scale with context size: the more context Claude processes, the more tokens you use. Claude Code automatically optimizes costs through prompt caching (which reduces costs for repeated content like system prompts) and auto-compaction (which summarizes conversation history when approaching context limits).


68 82 

69### Manage context proactively83### Manage context proactively

70 84 

71Use `/cost` to check your current token usage, or [configure your status line](/en/statusline#context-window-usage) to display it continuously.85Use `/usage` to check your current token usage, or [configure your status line](/en/statusline#context-window-usage) to display it continuously.

72 86 

73* **Clear between tasks**: Use `/clear` to start fresh when switching to unrelated work. Stale context wastes tokens on every subsequent message. Use `/rename` before clearing so you can easily find the session later, then `/resume` to return to it.87* **Clear between tasks**: Use `/clear` to start fresh when switching to unrelated work. Stale context wastes tokens on every subsequent message. Use `/rename` before clearing so you can easily find the session later, then `/resume` to return to it.

74* **Add custom compaction instructions**: `/compact Focus on code samples and API usage` tells Claude what to preserve during summarization.88* **Add custom compaction instructions**: `/compact Focus on code samples and API usage` tells Claude what to preserve during summarization.


87 101 

88### Reduce MCP server overhead102### Reduce MCP server overhead

89 103 

90Each MCP server adds tool definitions to your context, even when idle. Run `/context` to see what's consuming space.104MCP tool definitions are [deferred by default](/en/mcp#scale-with-mcp-tool-search), so only tool names enter context until Claude uses a specific tool. Run `/context` to see what's consuming space.

91 105 

92* **Prefer CLI tools when available**: Tools like `gh`, `aws`, `gcloud`, and `sentry-cli` are more context-efficient than MCP servers because they don't add persistent tool definitions. Claude can run CLI commands directly without the overhead.106* **Prefer CLI tools when available**: Tools like `gh`, `aws`, `gcloud`, and `sentry-cli` are still more context-efficient than MCP servers because they don't add any per-tool listing. Claude can run CLI commands directly.

93* **Disable unused servers**: Run `/mcp` to see configured servers and disable any you're not actively using.107* **Disable unused servers**: Run `/mcp` to see configured servers and disable any you're not actively using.

94* **Tool search is automatic**: When MCP tool descriptions exceed 10% of your context window, Claude Code automatically defers them and loads tools on-demand via [tool search](/en/mcp#scale-with-mcp-tool-search). Since deferred tools only enter context when actually used, a lower threshold means fewer idle tool definitions consuming space. Set a lower threshold with `ENABLE_TOOL_SEARCH=auto:<N>` (for example, `auto:5` triggers when tools exceed 5% of your context window).

95 108 

96### Install code intelligence plugins for typed languages109### Install code intelligence plugins for typed languages

97 110 


149 162 

150### Move instructions from CLAUDE.md to skills163### Move instructions from CLAUDE.md to skills

151 164 

152Your [CLAUDE.md](/en/memory) file is loaded into context at session start. If it contains detailed instructions for specific workflows (like PR reviews or database migrations), those tokens are present even when you're doing unrelated work. [Skills](/en/skills) load on-demand only when invoked, so moving specialized instructions into skills keeps your base context smaller. Aim to keep CLAUDE.md under \~500 lines by including only essentials.165Your [CLAUDE.md](/en/memory) file is loaded into context at session start. If it contains detailed instructions for specific workflows (like PR reviews or database migrations), those tokens are present even when you're doing unrelated work. [Skills](/en/skills) load on-demand only when invoked, so moving specialized instructions into skills keeps your base context smaller. Aim to keep CLAUDE.md under 200 lines by including only essentials.

153 166 

154### Adjust extended thinking167### Adjust extended thinking

155 168 

156Extended thinking is enabled by default with a budget of 31,999 tokens because it significantly improves performance on complex planning and reasoning tasks. However, thinking tokens are billed as output tokens, so for simpler tasks where deep reasoning isn't needed, you can reduce costs by disabling it in `/config` or lowering the budget (for example, `MAX_THINKING_TOKENS=8000`).169Extended thinking is enabled by default because it significantly improves performance on complex planning and reasoning tasks. Thinking tokens are billed as output tokens, and the default budget can be tens of thousands of tokens per request depending on the model. For simpler tasks where deep reasoning isn't needed, you can reduce costs by lowering the [effort level](/en/model-config#adjust-effort-level) with `/effort` or in `/model`, disabling thinking in `/config`, or lowering the budget with `MAX_THINKING_TOKENS=8000`.

157 170 

158### Delegate verbose operations to subagents171### Delegate verbose operations to subagents

159 172 

160Running tests, fetching documentation, or processing log files can consume significant context. Delegate these to [subagents](/en/sub-agents#isolate-high-volume-operations) so the verbose output stays in the subagent's context while only a summary returns to your main conversation.173Running tests, fetching documentation, or processing log files can consume significant context. Delegate these to [subagents](/en/sub-agents#isolate-high-volume-operations) so the verbose output stays in the subagent's context while only a summary returns to your main conversation.

161 174 

175### Manage agent team costs

176 

177Agent teams use approximately 7x more tokens than standard sessions when teammates run in plan mode, because each teammate maintains its own context window and runs as a separate Claude instance. Keep team tasks small and self-contained to limit per-teammate token usage. See [agent teams](/en/agent-teams) for details.

178 

162### Write specific prompts179### Write specific prompts

163 180 

164Vague requests like "improve this codebase" trigger broad scanning. Specific requests like "add input validation to the login function in auth.ts" let Claude work efficiently with minimal file reads.181Vague requests like "improve this codebase" trigger broad scanning. Specific requests like "add input validation to the login function in auth.ts" let Claude work efficiently with minimal file reads.


177Claude Code uses tokens for some background functionality even when idle:194Claude Code uses tokens for some background functionality even when idle:

178 195 

179* **Conversation summarization**: Background jobs that summarize previous conversations for the `claude --resume` feature196* **Conversation summarization**: Background jobs that summarize previous conversations for the `claude --resume` feature

180* **Command processing**: Some commands like `/cost` may generate requests to check status197* **Command processing**: Some commands like `/usage` may generate requests to check status

181 198 

182These background processes consume a small amount of tokens (typically under \$0.04 per session) even without active interaction.199These background processes consume a small amount of tokens (typically under \$0.04 per session) even without active interaction.

183 200 

184## Understanding changes in Claude Code behavior201## Understanding changes in Claude Code behavior

185 202 

186Claude Code regularly receives updates that may change how features work, including cost reporting. Run `claude --version` to check your current version. For specific billing questions, contact Anthropic support through your [Console account](https://platform.claude.com/login). For team deployments, start with a small pilot group to establish usage patterns before wider rollout.203Claude Code regularly receives updates that may change how features work, including cost reporting. Run `claude --version` to check your current version. For specific billing questions, contact Anthropic support through your [Console account](https://platform.claude.com/login).

data-usage.md +38 −17

Details

19 19 

20If you explicitly opt in to methods to provide us with materials to train on, such as via the [Development Partner Program](https://support.claude.com/en/articles/11174108-about-the-development-partner-program), we may use those materials provided to train our models. An organization admin can expressly opt-in to the Development Partner Program for their organization. Note that this program is available only for Anthropic first-party API, and not for Bedrock or Vertex users.20If you explicitly opt in to methods to provide us with materials to train on, such as via the [Development Partner Program](https://support.claude.com/en/articles/11174108-about-the-development-partner-program), we may use those materials provided to train our models. An organization admin can expressly opt-in to the Development Partner Program for their organization. Note that this program is available only for Anthropic first-party API, and not for Bedrock or Vertex users.

21 21 

22### Feedback using the `/bug` command22### Feedback using the `/feedback` command

23 23 

24If you choose to send us feedback about Claude Code using the `/bug` command, we may use your feedback to improve our products and services. Transcripts shared via `/bug` are retained for 5 years.24If you choose to send us feedback about Claude Code using the `/feedback` command, we may use your feedback to improve our products and services. Transcripts shared via `/feedback` are retained for 5 years.

25 25 

26### Session quality surveys26### Session quality surveys

27 27 

28When you see the "How is Claude doing this session?" prompt in Claude Code, responding to this survey (including selecting "Dismiss"), only your numeric rating (1, 2, 3, or dismiss) is recorded. We do not collect or store any conversation transcripts, inputs, outputs, or other session data as part of this survey. Unlike thumbs up/down feedback or `/bug` reports, this session quality survey is a simple product satisfaction metric. Your responses to this survey do not impact your data training preferences and cannot be used to train our AI models.28When you see the "How is Claude doing this session?" prompt in Claude Code, responding to this survey (including selecting "Dismiss"), only your numeric rating (1, 2, 3, or dismiss) is recorded. We do not collect or store any conversation transcripts, inputs, outputs, or other session data as part of this survey. Unlike thumbs up/down feedback or `/feedback` reports, this session quality survey is a simple product satisfaction metric. Your responses to this survey do not impact your data training preferences and cannot be used to train our AI models.

29 

30To disable these surveys, set `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1`. The survey is also disabled when `DISABLE_TELEMETRY` or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` is set. To control frequency instead of disabling, set [`feedbackSurveyRate`](/en/settings#available-settings) in your settings file to a probability between `0` and `1`.

29 31 

30### Data retention32### Data retention

31 33 


40**Commercial users (Team, Enterprise, and API)**:42**Commercial users (Team, Enterprise, and API)**:

41 43 

42* Standard: 30-day retention period44* Standard: 30-day retention period

43* Zero data retention: Available with appropriately configured API keys - Claude Code will not retain chat transcripts on servers45* [Zero data retention](/en/zero-data-retention): available for Claude Code on Claude for Enterprise. ZDR is enabled on a per-organization basis; each new organization must have ZDR enabled separately by your account team

44* Local caching: Claude Code clients may store sessions locally for up to 30 days to enable session resumption (configurable)46* Local caching: Claude Code clients store session transcripts locally in plaintext under `~/.claude/projects/` for 30 days by default to enable session resumption. Adjust the period with `cleanupPeriodDays`. See [application data](/en/claude-directory#application-data) for what's stored and how to clear it.

47 

48You can delete individual Claude Code on the web sessions at any time. Deleting a session permanently removes the session's event data. For instructions on how to delete sessions, see [Delete sessions](/en/claude-code-on-the-web#delete-sessions).

45 49 

46Learn more about data retention practices in our [Privacy Center](https://privacy.anthropic.com/).50Learn more about data retention practices in our [Privacy Center](https://privacy.anthropic.com/).

47 51 


49 53 

50## Data access54## Data access

51 55 

52For all first party users, you can learn more about what data is logged for [local Claude Code](#local-claude-code-data-flow-and-dependencies) and [remote Claude Code](#cloud-execution-data-flow-and-dependencies). Note for remote Claude Code, Claude accesses the repository where you initiate your Claude Code session. Claude does not access repositories that you have connected but have not started a session in.56For all first party users, you can learn more about what data is logged for [local Claude Code](#local-claude-code-data-flow-and-dependencies) and [remote Claude Code](#cloud-execution-data-flow-and-dependencies). [Remote Control](/en/remote-control) sessions follow the local data flow since all execution happens on your machine. Note for remote Claude Code, Claude accesses the repository where you initiate your Claude Code session. Claude does not access repositories that you have connected but have not started a session in.

53 57 

54## Local Claude Code: Data flow and dependencies58## Local Claude Code: Data flow and dependencies

55 59 

56The diagram below shows how Claude Code connects to external services during installation and normal operation. Solid lines indicate required connections, while dashed lines represent optional or user-initiated data flows.60The diagram below shows how Claude Code connects to external services during installation and normal operation. Solid lines indicate required connections, while dashed lines represent optional or user-initiated data flows.

57 61 

58<img src="https://mintcdn.com/claude-code/I9Dpo7RZuIbc86cX/images/claude-code-data-flow.svg?fit=max&auto=format&n=I9Dpo7RZuIbc86cX&q=85&s=9e77f476347e7c9983f6e211d27cf6a9" alt="Diagram showing Claude Code's external connections: install/update connects to NPM, and user requests connect to Anthropic services including Console auth, public-api, and optionally Statsig, Sentry, and bug reporting" data-og-width="720" width="720" data-og-height="520" height="520" data-path="images/claude-code-data-flow.svg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/I9Dpo7RZuIbc86cX/images/claude-code-data-flow.svg?w=280&fit=max&auto=format&n=I9Dpo7RZuIbc86cX&q=85&s=94c033b9b6db3d10b9e2d7c6d681d9dc 280w, https://mintcdn.com/claude-code/I9Dpo7RZuIbc86cX/images/claude-code-data-flow.svg?w=560&fit=max&auto=format&n=I9Dpo7RZuIbc86cX&q=85&s=430aaaf77c28c501d5753ffa456ee227 560w, https://mintcdn.com/claude-code/I9Dpo7RZuIbc86cX/images/claude-code-data-flow.svg?w=840&fit=max&auto=format&n=I9Dpo7RZuIbc86cX&q=85&s=63c3c3f160b522220a8291fe2f93f970 840w, https://mintcdn.com/claude-code/I9Dpo7RZuIbc86cX/images/claude-code-data-flow.svg?w=1100&fit=max&auto=format&n=I9Dpo7RZuIbc86cX&q=85&s=a7f6e838482f4a1a0a0b4683439369ea 1100w, https://mintcdn.com/claude-code/I9Dpo7RZuIbc86cX/images/claude-code-data-flow.svg?w=1650&fit=max&auto=format&n=I9Dpo7RZuIbc86cX&q=85&s=5fbf749c2f94babb3ef72edfb7aba1e9 1650w, https://mintcdn.com/claude-code/I9Dpo7RZuIbc86cX/images/claude-code-data-flow.svg?w=2500&fit=max&auto=format&n=I9Dpo7RZuIbc86cX&q=85&s=7a1babbdccc4986957698d9c5c30c4a8 2500w" />62<img src="https://mintcdn.com/claude-code/YcBW2H7CArGcduPb/images/claude-code-data-flow.svg?fit=max&auto=format&n=YcBW2H7CArGcduPb&q=85&s=b600a89f84fc86f9ff7be00a466c0635" alt="Diagram showing Claude Code's external connections: install/update connects to the distribution server, and user requests connect to Anthropic services including Console auth, public-api, and optionally Statsig, Sentry, and bug reporting" width="720" height="520" data-path="images/claude-code-data-flow.svg" />

63 

64Claude Code runs locally. To interact with the LLM, Claude Code sends data over the network. This data includes all user prompts and model outputs, encrypted in transit via TLS 1.2+. Claude Code is compatible with most popular VPNs and LLM proxies.

65 

66Encryption at rest depends on your model provider:

59 67 

60Claude Code is installed from [NPM](https://www.npmjs.com/package/@anthropic-ai/claude-code). Claude Code runs locally. In order to interact with the LLM, Claude Code sends data over the network. This data includes all user prompts and model outputs. The data is encrypted in transit via TLS and is not encrypted at rest. Claude Code is compatible with most popular VPNs and LLM proxies.68| Provider | Encryption at rest |

69| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |

70| Anthropic API | Infrastructure-level disk encryption (AES-256). Enable [Zero Data Retention](/en/zero-data-retention) for no server-side persistence. |

71| Amazon Bedrock | AES-256 with AWS-managed keys. Customer-managed keys available via AWS KMS. |

72| Google Cloud Vertex AI | Google-managed encryption keys. CMEK available. |

73| Microsoft Foundry | Requests route to Anthropic infrastructure with AES-256 disk encryption. |

61 74 

62Claude Code is built on Anthropic's APIs. For details regarding our API's security controls, including our API logging procedures, please refer to compliance artifacts offered in the [Anthropic Trust Center](https://trust.anthropic.com).75Claude Code is built on Anthropic's APIs. For details on API security controls, including API logging procedures, see the compliance artifacts in the [Anthropic Trust Center](https://trust.anthropic.com).

63 76 

64### Cloud execution: Data flow and dependencies77### Cloud execution: Data flow and dependencies

65 78 


78 91 

79Claude Code connects from users' machines to Sentry for operational error logging. The data is encrypted in transit using TLS and at rest using 256-bit AES encryption. Read more in the [Sentry security documentation](https://sentry.io/security/). To opt out of error logging, set the `DISABLE_ERROR_REPORTING` environment variable.92Claude Code connects from users' machines to Sentry for operational error logging. The data is encrypted in transit using TLS and at rest using 256-bit AES encryption. Read more in the [Sentry security documentation](https://sentry.io/security/). To opt out of error logging, set the `DISABLE_ERROR_REPORTING` environment variable.

80 93 

81When users run the `/bug` command, a copy of their full conversation history including code is sent to Anthropic. The data is encrypted in transit and at rest. Optionally, a Github issue is created in our public repository. To opt out of bug reporting, set the `DISABLE_BUG_COMMAND` environment variable.94When users run the `/feedback` command, a copy of their full conversation history including code is sent to Anthropic. The data is encrypted in transit via TLS. Optionally, a GitHub issue is created in the public repository. To opt out, set the `DISABLE_FEEDBACK_COMMAND` environment variable to `1`.

82 95 

83## Default behaviors by API provider96## Default behaviors by API provider

84 97 

85By default, we disable all non-essential traffic (including error reporting, telemetry, and bug reporting functionality) when using Bedrock or Vertex. You can also opt out of all of these at once by setting the `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` environment variable. Here are the full default behaviors:98By default, error reporting, telemetry, and bug reporting are disabled when using Bedrock, Vertex, or Foundry. Session quality surveys and the WebFetch domain safety check are exceptions and run regardless of provider. You can opt out of all non-essential traffic, including surveys, at once by setting `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`. This variable does not affect the WebFetch check, which has its own opt-out. Here are the full default behaviors:

99 

100| Service | Claude API | Vertex API | Bedrock API | Foundry API |

101| ------------------------------------ | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |

102| **Statsig (Metrics)** | Default on.<br />`DISABLE_TELEMETRY=1` to disable. | Default off.<br />`CLAUDE_CODE_USE_VERTEX` must be 1. | Default off.<br />`CLAUDE_CODE_USE_BEDROCK` must be 1. | Default off.<br />`CLAUDE_CODE_USE_FOUNDRY` must be 1. |

103| **Sentry (Errors)** | Default on.<br />`DISABLE_ERROR_REPORTING=1` to disable. | Default off.<br />`CLAUDE_CODE_USE_VERTEX` must be 1. | Default off.<br />`CLAUDE_CODE_USE_BEDROCK` must be 1. | Default off.<br />`CLAUDE_CODE_USE_FOUNDRY` must be 1. |

104| **Claude API (`/feedback` reports)** | Default on.<br />`DISABLE_FEEDBACK_COMMAND=1` to disable. | Default off.<br />`CLAUDE_CODE_USE_VERTEX` must be 1. | Default off.<br />`CLAUDE_CODE_USE_BEDROCK` must be 1. | Default off.<br />`CLAUDE_CODE_USE_FOUNDRY` must be 1. |

105| **Session quality surveys** | Default on.<br />`CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1` to disable. | Default on.<br />`CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1` to disable. | Default on.<br />`CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1` to disable. | Default on.<br />`CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1` to disable. |

106| **WebFetch domain safety check** | Default on.<br />`skipWebFetchPreflight: true` in [settings](/en/settings) to disable. | Default on.<br />`skipWebFetchPreflight: true` in [settings](/en/settings) to disable. | Default on.<br />`skipWebFetchPreflight: true` in [settings](/en/settings) to disable. | Default on.<br />`skipWebFetchPreflight: true` in [settings](/en/settings) to disable. |

107 

108All environment variables can be checked into `settings.json` (see [settings reference](/en/settings)).

109 

110### WebFetch domain safety check

86 111 

87| Service | Claude API | Vertex API | Bedrock API |112Before fetching a URL, the WebFetch tool sends the requested hostname to `api.anthropic.com` to check it against a safety blocklist maintained by Anthropic. Only the hostname is sent, not the full URL, path, or page contents. Results are cached per hostname for five minutes.

88| ------------------------------- | -------------------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------ |

89| **Statsig (Metrics)** | Default on.<br />`DISABLE_TELEMETRY=1` to disable. | Default off.<br />`CLAUDE_CODE_USE_VERTEX` must be 1. | Default off.<br />`CLAUDE_CODE_USE_BEDROCK` must be 1. |

90| **Sentry (Errors)** | Default on.<br />`DISABLE_ERROR_REPORTING=1` to disable. | Default off.<br />`CLAUDE_CODE_USE_VERTEX` must be 1. | Default off.<br />`CLAUDE_CODE_USE_BEDROCK` must be 1. |

91| **Claude API (`/bug` reports)** | Default on.<br />`DISABLE_BUG_COMMAND=1` to disable. | Default off.<br />`CLAUDE_CODE_USE_VERTEX` must be 1. | Default off.<br />`CLAUDE_CODE_USE_BEDROCK` must be 1. |

92 113 

93All environment variables can be checked into `settings.json` ([read more](/en/settings)).114This check runs regardless of which model provider you use and is not affected by `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`. If your network blocks `api.anthropic.com`, WebFetch requests fail until you either allowlist the domain or set `skipWebFetchPreflight: true` in [settings](/en/settings). Disabling the check means WebFetch attempts to retrieve any URL without consulting the blocklist, so combine it with [`WebFetch` permission rules](/en/permissions#webfetch) if you need to restrict which domains Claude can reach.

debug-your-config.md +96 −0 added

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# Debug your configuration

6 

7> Diagnose why CLAUDE.md, settings, hooks, MCP servers, or skills aren't taking effect. Use /context, /doctor, /hooks, and /mcp to see what actually loaded.

8 

9When Claude ignores an instruction or a feature you configured doesn't appear, the cause is usually that the file didn't load, it loaded from a different location than you expected, or another file overrode it. This guide shows how to inspect what Claude Code actually loaded so you can narrow down which applies.

10 

11For installation, authentication, and connectivity problems, see [Troubleshooting](/en/troubleshooting) instead.

12 

13## See what loaded into context

14 

15The `/context` command shows everything occupying the context window for the current session, broken down by category: system prompt, memory files, skills, MCP tools, and conversation messages. Run it first to confirm whether your `CLAUDE.md`, rules, or skill descriptions are present at all.

16 

17For detail on a specific category, follow up with the dedicated command:

18 

19| Command | Shows |

20| :------------- | :-------------------------------------------------------------------------- |

21| `/memory` | Which `CLAUDE.md` and rules files loaded, plus auto-memory entries |

22| `/skills` | Available skills from project, user, and plugin sources |

23| `/agents` | Configured subagents and their settings |

24| `/hooks` | Active hook configurations |

25| `/mcp` | Connected MCP servers and their status |

26| `/permissions` | Resolved allow and deny rules currently in effect |

27| `/doctor` | Configuration diagnostics: invalid keys, schema errors, installation health |

28| `/status` | Active settings sources, including whether managed settings are in effect |

29 

30If a memory file is missing from `/memory`, check its location against [how CLAUDE.md files load](/en/memory#how-claude-md-files-load). Subdirectory `CLAUDE.md` files load on demand when Claude reads a file in that directory with the Read tool, not at session start.

31 

32If `/memory` confirms the file loaded but Claude still isn't following a particular instruction, the issue is likely how the instruction is written rather than whether it loaded. CLAUDE.md works well for the kinds of guidance you'd give a new teammate, such as project conventions, build commands, and where files belong.

33 

34Adherence drops when an instruction is vague enough to interpret multiple ways, when two files give conflicting direction, or when the file has grown long enough that individual rules get less attention. [Write effective instructions](/en/memory#write-effective-instructions) covers the specificity, size, and structure patterns that keep adherence high.

35 

36<Note>

37 CLAUDE.md and permissions solve different problems. CLAUDE.md tells Claude how your project works so it makes good decisions. [Permissions](/en/permissions) and [hooks](/en/hooks) enforce limits regardless of what Claude decides. Use CLAUDE.md for "we do it this way here." Use permissions or hooks for security boundaries and anything that must never happen, where you need a guarantee instead of guidance.

38</Note>

39 

40## Check resolved settings

41 

42Settings merge across managed, user, project, and local scopes. Managed settings always win when present. Among the rest, the closer scope overrides the broader one in the order local, then project, then user. Some settings can also be set by command-line flags or [environment variables](/en/env-vars), which act as another override layer. When a setting doesn't seem to apply, the value you set is usually being overridden by another scope or an environment variable.

43 

44Run `/doctor` to validate your configuration files and surface invalid keys or schema errors. Run `/status` to see which settings sources are active, including whether managed settings are in effect. To understand which scope wins for a given key, see [How scopes interact](/en/settings#how-scopes-interact).

45 

46## Check MCP servers

47 

48Run `/mcp` to see every configured server, its connection status, and whether you have approved it for the current project. A server can be defined correctly but still not provide tools for a few common reasons:

49 

50* Project-scoped servers in `.mcp.json` require a one-time approval. If the prompt was dismissed, the server stays disabled until you approve it from `/mcp`.

51* A server that fails to start shows as failed in `/mcp`. Relative file paths in `command` or `args` are a frequent cause, since they resolve against the directory you launched Claude Code from rather than the location of `.mcp.json`.

52* A server that shows as connected but lists zero tools has started successfully but isn't returning a tool list. Select **Reconnect** from `/mcp`. If the count stays at zero, run `claude --debug mcp` to see the server's stderr output.

53 

54For configuration locations and scope rules, see [MCP](/en/mcp).

55 

56## Check hooks

57 

58Run `/hooks` to list every hook registered for the current session, grouped by event. If a hook you defined doesn't appear, it isn't being read: hooks go under the `"hooks"` key in a settings file, not in a standalone file.

59 

60If the hook appears but doesn't fire, the matcher is the usual cause. The `matcher` field is a single string that uses `|` to match multiple tool names, for example `"Edit|Write"`. A misspelled tool name fails silently because the matcher never matches. An array value is a schema error: Claude Code shows a settings error notice, `/doctor` reports the validation failure, and the hook entry is dropped so it won't appear in `/hooks`.

61 

62Edits to `settings.json` take effect in the running session after a brief file-stability delay. You don't need to restart. If `/hooks` still shows the old definition a few seconds after saving, run `/hooks` again to refresh the view.

63 

64If `/hooks` shows the hook but it still does not fire, the next step is to watch hook evaluation live. Start a session with `claude --debug hooks` and trigger the tool call. The debug log records each event, which matchers were checked, and the hook's exit code and output. See [Debug hooks](/en/hooks#debug-hooks) for the log format and [hooks troubleshooting](/en/hooks-guide#limitations-and-troubleshooting) for common failure patterns.

65 

66## Common causes

67 

68Most configuration surprises trace back to a small set of location and syntax rules. Check these before assuming a bug:

69 

70| Symptom | Cause | Fix |

71| :--------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

72| Hook never fires | `matcher` is a JSON array instead of a string | Use a single string with `\|` to match multiple tools, for example `"Edit\|Write"`. See [matcher patterns](/en/hooks#matcher-patterns). |

73| Hook never fires | `matcher` value is lowercase, for example `"bash"` | Matching is case-sensitive. Tool names are capitalized: `Bash`, `Edit`, `Write`, `Read`. |

74| Hook never fires | Hooks are in a standalone `.claude/hooks.json` file | There is no standalone hooks file. Define hooks under the `"hooks"` key in `settings.json`. See [hook configuration](/en/hooks). |

75| Permissions, hooks, or env set globally are ignored | Configuration was added to `~/.claude.json` | `~/.claude.json` holds app state and UI toggles. `permissions`, `hooks`, and `env` belong in `~/.claude/settings.json`. These are two different files. |

76| A `settings.json` value seems ignored | The same key is set in `settings.local.json` | `settings.local.json` overrides `settings.json`, and both override `~/.claude/settings.json`. See [settings precedence](/en/settings#how-scopes-interact). |

77| Skill doesn't appear in `/skills` | Skill file is at `.claude/skills/name.md` instead of in a folder | Use a folder with `SKILL.md` inside: `.claude/skills/name/SKILL.md`. |

78| Skill appears in `/skills` but Claude never invokes it | Skill has `disable-model-invocation: true` in its frontmatter, or its description doesn't match how you phrase the request | Check the badge in `/skills`: a "user-only" label means Claude won't trigger it on its own. See [skill invocation](/en/skills). |

79| Subdirectory `CLAUDE.md` instructions seem ignored | Subdirectory files load on demand, not at session start | They load when Claude reads a file in that directory with the Read tool, not at launch and not when writing or creating files there. See [how CLAUDE.md files load](/en/memory#how-claude-md-files-load). |

80| Subagent ignores `CLAUDE.md` instructions | Subagents don't always inherit project memory | Put critical rules in the agent file body, which becomes the subagent's system prompt. See [subagent configuration](/en/sub-agents). |

81| Cleanup logic never runs at session end | No `SessionEnd` hook configured | `SessionStart` and `SessionEnd` both exist. See the [hook events list](/en/hooks#hook-events). |

82| MCP servers in `.mcp.json` never load | File is under `.claude/` or uses Claude Desktop's config format | Project MCP config goes at the repository root as `.mcp.json`, not inside `.claude/`. See [MCP configuration](/en/mcp). |

83| Project MCP server added but doesn't appear | The one-time approval prompt was dismissed | Project-scoped servers require approval. Run `/mcp` to see status and approve. |

84| MCP server fails to start from some directories | `command` or `args` uses a relative file path | Use absolute paths for local scripts. Executables on your `PATH` like `npx` or `uvx` work as-is. |

85| MCP server starts without expected environment variables | Variables are in `settings.json` `env`, which doesn't propagate to MCP child processes | Set per-server `env` inside `.mcp.json` instead. |

86| `Bash(rm *)` deny rule doesn't block `/bin/rm` or `find -delete` | Prefix rules match the literal command string, not the underlying executable | Add explicit patterns for each variant, or use a [PreToolUse hook](/en/hooks-guide) or the [sandbox](/en/sandboxing) for a hard guarantee. |

87 

88## Related resources

89 

90For full reference on each configuration surface, see the dedicated page:

91 

92* **[`.claude` directory reference](/en/claude-directory)**: every config file location and what reads it

93* **[Settings](/en/settings)**: precedence order and the full key list

94* **[Hooks reference](/en/hooks)**: event names, payloads, and `--debug hooks` output format

95* **[MCP](/en/mcp)**: server configuration, approval, and `/mcp` output

96* **[Troubleshooting](/en/troubleshooting)**: `claude doctor`, platform issues, and installation problems

desktop.md +625 −165

Details

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> 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.3> Use this file to discover all available pages before exploring further.

4 4 

5# Claude Code on desktop5# Use Claude Code Desktop

6 6 

7> Run Claude Code tasks locally or on secure cloud infrastructure with the Claude desktop app7> Get more out of Claude Code Desktop: parallel sessions with Git isolation, drag-and-drop pane layout, integrated terminal and file editor, side chats, computer use, Dispatch sessions from your phone, visual diff review, app previews, PR monitoring, connectors, and enterprise configuration.

8 8 

9<Note>9The Claude Desktop app has three tabs: **Chat** for conversations, **Cowork** for [Dispatch and longer agentic work](https://claude.com/product/cowork), and **Code** for software development. This page is the reference for the Code tab.

10 Claude Code on desktop is currently in preview.

11</Note>

12 

13Claude Code is an AI coding assistant that works directly with your codebase. Unlike Claude.ai chat, it can read your project files, edit code, run terminal commands, and understand how different parts of your code connect. You watch changes happen in real time.

14 

15You can use Claude Code through the terminal ([CLI](/en/quickstart)) or through the desktop app described here. Both provide the same core capabilities. The desktop app adds a graphical interface and visual session management.

16 10 

17<CardGroup cols={2}>11<CardGroup cols={2}>

18 <Card title="New to Claude Code?" icon="rocket" href="#installation-and-setup">12 <Card title="Download for macOS" icon="apple" href="https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code&utm_medium=docs">

19 Start here to install and make your first edit13 Universal build for Intel and Apple Silicon

20 </Card>14 </Card>

21 15 

22 <Card title="Coming from the CLI?" icon="terminal" href="#how-desktop-relates-to-cli">16 <Card title="Download for Windows" icon="windows" href="https://claude.ai/api/desktop/win32/x64/setup/latest/redirect?utm_source=claude_code&utm_medium=docs">

23 See what's shared and what's different17 For x64 processors

24 </Card>18 </Card>

25</CardGroup>19</CardGroup>

26 20 

27The desktop app has three tabs:21For Windows ARM64, download the [ARM64 installer](https://claude.ai/api/desktop/win32/arm64/setup/latest/redirect?utm_source=claude_code\&utm_medium=docs). Linux is not supported.

28 22 

29* **Chat**: A conversational interface for general questions and tasks (like Claude.ai)23After installing, launch Claude, sign in, and click the **Code** tab. The first time you open it on Windows, you need [Git for Windows](https://git-scm.com/downloads/win) installed; restart the app after installing it. For a walkthrough of your first session, see the [Get started guide](/en/desktop-quickstart).

30* **Cowork**: An autonomous agent that works on tasks in the background

31* **Code**: An AI coding assistant that reads and edits your project files directly

32 24 

33This documentation covers the **Code** tab. For the chat interface, see the [Claude Desktop support articles](https://support.claude.com/en/collections/16163169-claude-desktop).25In the Code tab, each conversation is a **session**: it has its own chat history, project folder, and code changes, independent of any other session. The sidebar lists your sessions and lets you run several in parallel. Within a session you can:

34 26 

35## Installation and setup27* [Review and comment on diffs](#review-changes-with-diff-view), then [watch the resulting PR through CI](#monitor-pull-request-status)

28* [Preview your running app](#preview-your-app) in an embedded browser while Claude verifies its own changes

29* [Arrange panes](#arrange-your-workspace) for the chat, diff, preview, terminal, and file editor side by side

30* Ask a [side question](#ask-a-side-question-without-derailing-the-session) that uses the session's context without derailing it

31* [Connect external tools](#connect-external-tools) like GitHub, Slack, and Linear

32* Let Claude [open apps and control your screen](#let-claude-use-your-computer)

33* Run on your machine, in the [cloud](#run-long-running-tasks-remotely), or over [SSH](#ssh-sessions)

36 34 

37<Steps>35For [scheduled recurring work](/en/desktop-scheduled-tasks), [keyboard shortcuts](#keyboard-shortcuts), or [sending tasks from your phone](#sessions-from-dispatch), see the linked pages and sections. If you already use the terminal-based CLI, see the [CLI comparison](#coming-from-the-cli) for what carries over.

38 <Step title="Download the app">

39 Download Claude for your platform. You'll need an Anthropic account ([sign up at claude.ai](https://claude.ai) if you don't have one).

40 36 

41 <CardGroup cols={2}>37## Start a session

42 <Card title="macOS" icon="apple" href="https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code&utm_medium=docs">

43 Universal build for Intel and Apple Silicon

44 </Card>

45 38 

46 <Card title="Windows" icon="windows" href="https://claude.ai/api/desktop/win32/x64/exe/latest/redirect?utm_source=claude_code&utm_medium=docs">39Before you send your first message, configure four things in the prompt area:

47 For x64 processors

48 </Card>

49 </CardGroup>

50 40 

51 For Windows ARM64, [download here](https://claude.ai/api/desktop/win32/arm64/exe/latest/redirect?utm_source=claude_code\&utm_medium=docs). Local sessions are not available on ARM64 devices, so use remote sessions instead.41* **Environment**: choose where Claude runs. Select **Local** for your machine, **Remote** for Anthropic-hosted cloud sessions, or an [**SSH connection**](#ssh-sessions) for a remote machine you manage. See [environment configuration](#environment-configuration).

42* **Project folder**: select the folder or repository Claude works in. For remote sessions, you can add [multiple repositories](#run-long-running-tasks-remotely).

43* **Model**: pick a [model](/en/model-config#available-models) from the dropdown next to the send button. You can change this during the session.

44* **Permission mode**: choose how much autonomy Claude has from the [mode selector](#choose-a-permission-mode). You can change this during the session.

52 45 

53 Linux is not currently supported.46Type your task and press **Enter** to start. Each session tracks its own context and changes independently.

54 </Step>

55 47 

56 <Step title="Open the app and sign in">48## Work with code

57 Launch Claude from your Applications folder (macOS) or Start menu (Windows). Sign in with your Anthropic account.

58 </Step>

59 49 

60 <Step title="Select the Code tab">50Give Claude the right context, control how much it does on its own, and review what it changed.

61 Click the **Code** tab in the top left. If clicking Code prompts you to sign in online, complete the sign-in and restart the app.

62 </Step>

63</Steps>

64 51 

65## Getting started52### Use the prompt box

66 53 

67If you already use the CLI, you can skip to [How Desktop relates to CLI](#how-desktop-relates-to-cli) for a quick overview of differences.54Type what you want Claude to do and press **Enter** to send. Claude reads your project files, makes changes, and runs commands based on your [permission mode](#choose-a-permission-mode). You can interrupt Claude at any point: click the stop button or type your correction and press **Enter**. Claude stops what it's doing and adjusts based on your input.

68 55 

69<Steps>56The **+** button next to the prompt box gives you access to file attachments, [skills](#use-skills), [connectors](#connect-external-tools), and [plugins](#install-plugins).

70 <Step title="Choose a folder and environment">

71 Select **Local** to run Claude on your machine using your files directly. This is the best choice for getting started. Click **Select folder** and choose your project directory.

72 57 

73 You can also run [remote sessions](/en/claude-code-on-the-web) that continue in the cloud even if you close the app.58### Add files and context to prompts

74 </Step>59 

60The prompt box supports two ways to bring in external context:

61 

62* **@mention files**: type `@` followed by a filename to add a file to the conversation context. Claude can then read and reference that file. @mention is not available in remote sessions.

63* **Attach files**: attach images, PDFs, and other files to your prompt using the attachment button, or drag and drop files directly into the prompt. This is useful for sharing screenshots of bugs, design mockups, or reference documents.

64 

65### Choose a permission mode

66 

67Permission modes control how much autonomy Claude has during a session: whether it asks before editing files, running commands, or both. You can switch modes at any time using the mode selector next to the send button. Start with Ask permissions to see exactly what Claude does, then move to Auto accept edits or Plan mode as you get comfortable.

68 

69| Mode | Settings key | Behavior |

70| ---------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

71| **Ask permissions** | `default` | Claude asks before editing files or running commands. You see a diff and can accept or reject each change. Recommended for new users. |

72| **Auto accept edits** | `acceptEdits` | Claude auto-accepts file edits and common filesystem commands like `mkdir`, `touch`, and `mv`, but still asks before running other terminal commands. Use this when you trust file changes and want faster iteration. |

73| **Plan mode** | `plan` | Claude reads files and runs commands to explore, then proposes a plan without editing your source code. Good for complex tasks where you want to review the approach first. |

74| **Auto** | `auto` | Claude executes all actions with background safety checks that verify alignment with your request. Reduces permission prompts while maintaining oversight. Enable in your Settings → Claude Code. See [availability requirements](#auto-mode-availability) below. |

75| **Bypass permissions** | `bypassPermissions` | Claude runs without any permission prompts, equivalent to `--dangerously-skip-permissions` in the CLI. Enable in your Settings → Claude Code under "Allow bypass permissions mode". Only use this in sandboxed containers or VMs. Enterprise admins can disable this option. |

76 

77The `dontAsk` permission mode is available only in the [CLI](/en/permission-modes#allow-only-pre-approved-tools-with-dontask-mode).

78 

79<span id="auto-mode-availability" />

80 

81Auto mode is a research preview available on Max, Team, Enterprise, and API plans. It is not available on Pro plans or third-party providers. On Team, Enterprise, and API plans it requires Claude Sonnet 4.6, Opus 4.6, or Opus 4.7. On Max plans it requires Claude Opus 4.7.

82 

83<Tip title="Best practice">

84 Start complex tasks in Plan mode so Claude maps out an approach before making changes. Once you approve the plan, switch to Auto accept edits or Ask permissions to execute it. See [explore first, then plan, then code](/en/best-practices#explore-first-then-plan-then-code) for more on this workflow.

85</Tip>

86 

87Remote sessions support Auto accept edits and Plan mode. Ask permissions is not available because remote sessions auto-accept file edits by default, and Bypass permissions is not available because the remote environment is already sandboxed.

88 

89Enterprise admins can restrict which permission modes are available. See [enterprise configuration](#enterprise-configuration) for details.

90 

91### Preview your app

92 

93Claude can start a dev server and open an embedded browser to verify its changes. This works for frontend web apps as well as backend servers: Claude can test API endpoints, view server logs, and iterate on issues it finds. In most cases, Claude starts the server automatically after editing project files. You can also ask Claude to preview at any time. By default, Claude [auto-verifies](#auto-verify-changes) changes after every edit.

94 

95The preview pane can also open static HTML files, PDFs, images, and videos from your project. Click an HTML, PDF, image, or video path in the chat to open it in preview.

96 

97From the preview pane, you can:

98 

99* Interact with your running app directly in the embedded browser

100* Watch Claude verify its own changes automatically: it takes screenshots, inspects the DOM, clicks elements, fills forms, and fixes issues it finds

101* Start or stop servers from the **Preview** dropdown in the session toolbar

102* Persist cookies and local storage across server restarts by selecting **Persist sessions** in the dropdown, so you don't have to re-login during development

103* Edit the server configuration or stop all servers at once

104 

105Claude creates the initial server configuration based on your project. If your app uses a custom dev command, edit `.claude/launch.json` to match your setup. See [Configure preview servers](#configure-preview-servers) for the full reference.

106 

107To clear saved session data, toggle **Persist preview sessions** off in Settings → Claude Code. To disable preview entirely, toggle off **Preview** in Settings → Claude Code.

108 

109### Review changes with diff view

110 

111After Claude makes changes to your code, the diff view lets you review modifications file by file before creating a pull request.

112 

113When Claude changes files, a diff stats indicator appears showing the number of lines added and removed, such as `+12 -1`. Click this indicator to open the diff viewer, which displays a file list on the left and the changes for each file on the right.

114 

115To comment on specific lines, click any line in the diff to open a comment box. Type your feedback and press **Enter** to add the comment. After adding comments to multiple lines, submit all comments at once:

116 

117* **macOS**: press **Cmd+Enter**

118* **Windows**: press **Ctrl+Enter**

119 

120Claude reads your comments and makes the requested changes, which appear as a new diff you can review.

121 

122### Review your code

123 

124In the diff view, click **Review code** in the top-right toolbar to ask Claude to evaluate the changes before you commit. Claude examines the current diffs and leaves comments directly in the diff view. You can respond to any comment or ask Claude to revise.

125 

126The review focuses on high-signal issues: compile errors, definite logic errors, security vulnerabilities, and obvious bugs. It does not flag style, formatting, pre-existing issues, or anything a linter would catch.

75 127 

76 <Step title="Start a session">128### Monitor pull request status

77 Type what you want Claude to do:

78 129 

79 * "Find a TODO comment and fix it"130After you open a pull request, a CI status bar appears in the session. Claude Code uses the GitHub CLI to poll check results and surface failures.

80 * "Add tests for the main function"

81 * "Create a CLAUDE.md with instructions for this codebase"

82 131 

83 A **session** is a conversation with Claude about your code. Each session tracks its own context and changes, so you can work on multiple tasks without them interfering with each other.132* **Auto-fix**: when enabled, Claude automatically attempts to fix failing CI checks by reading the failure output and iterating.

133* **Auto-merge**: when enabled, Claude merges the PR once all checks pass. The merge method is squash. Auto-merge must be [enabled in your GitHub repository settings](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-auto-merge-for-pull-requests-in-your-repository) for this to work.

134 

135Use the **Auto-fix** and **Auto-merge** toggles in the CI status bar to enable either option. Claude Code also sends a desktop notification when CI finishes. To archive the session automatically once the PR merges or closes, turn on [auto-archive](#work-in-parallel-with-sessions) in Settings → Claude Code.

136 

137<Note>

138 PR monitoring requires the [GitHub CLI (`gh`)](https://cli.github.com/) to be installed and authenticated on your machine. If `gh` is not installed, Desktop prompts you to install it the first time you try to create a PR.

139</Note>

140 

141## Arrange your workspace

142 

143The Code tab is built around panes you can arrange in any layout: chat, diff, preview, terminal, file, plan, tasks, and subagent. Drag a pane by its header to reposition it, or drag a pane edge to resize it. Press **Cmd+\\** on macOS or **Ctrl+\\** on Windows to close the focused pane. Open additional panes from the **Views** menu in the session toolbar.

144 

145<Note>

146 The pane layout, terminal, file editor, and view modes in this section require Claude Desktop v1.2581.0 or later. Open **Claude → Check for Updates** on macOS or **Help → Check for Updates** on Windows to update.

147</Note>

148 

149### Run commands in the terminal

150 

151The integrated terminal lets you run commands alongside your session without switching to another app. Open it from the **Views** menu or press **Ctrl+\`** on macOS or Windows. The terminal opens in your session's working directory and shares the same environment as Claude, so commands like `npm test` or `git status` see the same files Claude is editing. The terminal is available in local sessions only.

152 

153### Open and edit files

154 

155Click a file path in the chat or diff viewer to open it in the file pane. HTML, PDF, image, and video paths open in the [preview pane](#preview-your-app) instead. Make spot edits and click **Save** to write them back. If the file changed on disk since you opened it, the pane warns you and lets you override or discard. Click **Discard** to revert your edits, or click the path in the pane header to copy the absolute path.

156 

157The file pane is available in local and SSH sessions. For remote sessions, ask Claude to make the change.

158 

159### Open files in other apps

160 

161Right-click any file path in the chat, diff viewer, or file pane to open a context menu:

162 

163* **Attach as context**: add the file to your next prompt

164* **Open in**: open the file in an installed editor such as VS Code, Cursor, or Zed

165* **Show in Finder** on macOS, **Show in Explorer** on Windows: open the containing folder

166* **Copy path**: copy the absolute path to your clipboard

167 

168### Switch view modes

169 

170View modes control how much detail appears in the chat transcript. Switch modes from the **Transcript view** dropdown next to the send button, or press **Ctrl+O** on macOS or Windows to cycle through them.

171 

172| Mode | What it shows |

173| ----------- | -------------------------------------------------------------- |

174| **Normal** | Tool calls collapsed into summaries, with full text responses |

175| **Verbose** | Every tool call, file read, and intermediate step Claude takes |

176| **Summary** | Only Claude's final responses and the changes it made |

177 

178Use Verbose when debugging why Claude took a particular action. Use Summary when you're running multiple sessions and want to scan results quickly.

179 

180### Keyboard shortcuts

181 

182Press **Cmd+/** on macOS or **Ctrl+/** on Windows to see all shortcuts available in the Code tab. On Windows, use **Ctrl** in place of **Cmd** for the shortcuts below. Session cycling, the terminal toggle, and the view-mode toggle use **Ctrl** on every platform.

183 

184| Shortcut | Action |

185| ------------------------------------- | ---------------------------- |

186| `Cmd` `/` | Show keyboard shortcuts |

187| `Cmd` `N` | New session |

188| `Cmd` `W` | Close session |

189| `Ctrl` `Tab` / `Ctrl` `Shift` `Tab` | Next or previous session |

190| `Cmd` `Shift` `]` / `Cmd` `Shift` `[` | Next or previous session |

191| `Esc` | Stop Claude's response |

192| `Cmd` `Shift` `D` | Toggle diff pane |

193| `Cmd` `Shift` `P` | Toggle preview pane |

194| `Cmd` `Shift` `S` | Select an element in preview |

195| `Ctrl` `` ` `` | Toggle terminal pane |

196| `Cmd` `\` | Close focused pane |

197| `Cmd` `;` | Open side chat |

198| `Ctrl` `O` | Cycle view modes |

199| `Cmd` `Shift` `M` | Open permission mode menu |

200| `Cmd` `Shift` `I` | Open model menu |

201| `Cmd` `Shift` `E` | Open effort menu |

202| `1`–`9` | Select item in an open menu |

203 

204These shortcuts apply only to the Code tab. The terminal-based [interactive mode shortcuts](/en/interactive-mode#keyboard-shortcuts), such as `Shift+Tab` to cycle modes, do not apply in Desktop.

205 

206### Check usage

207 

208Click the usage ring next to the model picker to see your current context window usage and your plan usage for the period. Context usage is per session; plan usage is shared across all your Claude Code surfaces.

209 

210## Let Claude use your computer

211 

212Computer use lets Claude open your apps, control your screen, and work directly on your machine the way you would. Ask Claude to test a native app in a mobile simulator, interact with a desktop tool that has no CLI, or automate something that only works through a GUI.

213 

214<Note>

215 Computer use is a research preview on macOS and Windows that requires a Pro or Max plan. It is not available on Team or Enterprise plans. The Claude Desktop app must be running.

216</Note>

217 

218Computer use is off by default. [Enable it in Settings](#enable-computer-use) before Claude can control your screen. On macOS, you also need to grant Accessibility and Screen Recording permissions.

219 

220<Warning>

221 Unlike the [sandboxed Bash tool](/en/sandboxing), computer use runs on your actual desktop with access to whatever you approve. Claude checks each action and flags potential prompt injection from on-screen content, but the trust boundary is different. See the [computer use safety guide](https://support.claude.com/en/articles/14128542) for best practices.

222</Warning>

223 

224### When computer use applies

225 

226Claude has several ways to interact with an app or service, and computer use is the broadest and slowest. It tries the most precise tool first:

227 

228* If you have a [connector](#connect-external-tools) for a service, Claude uses the connector.

229* If the task is a shell command, Claude uses Bash.

230* If the task is browser work and you have [Claude in Chrome](/en/chrome) set up, Claude uses that.

231* If none of those apply, Claude uses computer use.

232 

233The [per-app access tiers](#app-permissions) reinforce this: browsers are capped at view-only, and terminals and IDEs at click-only, steering Claude toward the dedicated tool even when computer use is active. Screen control is reserved for things nothing else can reach, like native apps, hardware control panels, mobile simulators, or proprietary tools without an API.

234 

235### Enable computer use

236 

237Computer use is off by default. If you ask Claude to do something that needs it while it's off, Claude tells you it could do the task if you enable computer use in Settings.

238 

239<Steps>

240 <Step title="Update the desktop app">

241 Make sure you have the latest version of Claude Desktop. Download or update at [claude.com/download](https://claude.com/download), then restart the app.

84 </Step>242 </Step>

85 243 

86 <Step title="Review and accept changes">244 <Step title="Turn on the toggle">

87 By default, Code is in **Ask** mode, where Claude proposes changes and waits for your approval before applying them. You'll see:245 In the desktop app, go to **Settings > General** (under **Desktop app**). Find the **Computer use** toggle and turn it on. On Windows, the toggle takes effect immediately and setup is complete. On macOS, continue to the next step.

88 246 

89 1. **A diff view** showing exactly what will change in each file247 If you don't see the toggle, confirm you're on macOS or Windows with a Pro or Max plan, then update and restart the app.

90 2. **Accept/Reject buttons** to approve or decline each change248 </Step>

91 3. **Real-time updates** as Claude works through your request249 

250 <Step title="Grant macOS permissions">

251 On macOS, grant two system permissions before the toggle takes effect:

252 

253 * **Accessibility**: lets Claude click, type, and scroll

254 * **Screen Recording**: lets Claude see what's on your screen

92 255 

93 If you reject a change, Claude will ask how you'd like to proceed differently. Your files aren't modified until you accept.256 The Settings page shows the current status of each permission. If either is denied, click the badge to open the relevant System Settings pane.

94 </Step>257 </Step>

95</Steps>258</Steps>

96 259 

97The sections below cover commands, permission modes, parallel sessions, and ways to extend Claude Code with custom workflows and integrations.260### App permissions

98 261 

99## What you can do262The first time Claude needs to use an app, a prompt appears in your session. Click **Allow for this session** or **Deny**. Approvals last for the current session, or 30 minutes in [Dispatch-spawned sessions](#sessions-from-dispatch).

100 263 

101Claude Code can edit files, run terminal commands, and understand how your code connects. Try prompts like:264The prompt also shows what level of control Claude gets for that app. These tiers are fixed by app category and can't be changed:

102 265 

103* `Fix the bug in the login function`266| Tier | What Claude can do | Applies to |

104* `Run the tests and fix any failures`267| :----------- | :------------------------------------------------------- | :-------------------------- |

105* `How does the authentication flow work?`268| View only | See the app in screenshots | Browsers, trading platforms |

269| Click only | Click and scroll, but not type or use keyboard shortcuts | Terminals, IDEs |

270| Full control | Click, type, drag, and use keyboard shortcuts | Everything else |

106 271 

107You can rename, resume, and archive sessions through the sidebar.272Apps with broad reach, like terminals, Finder or File Explorer, and System Settings or Settings, show an extra warning in the prompt so you know what approving them grants.

108 

109### Choose a permission mode

110 273 

111Control how Claude works using the mode selector next to the send button:274You can configure two settings in **Settings > General** (under **Desktop app**):

112 275 

113* **Ask** (recommended for new users): Claude asks for your approval before each file edit or command. You see a diff view and can accept or reject each change.276* **Denied apps**: add apps here to reject them without prompting. Claude may still affect a denied app indirectly through actions in an allowed app, but it can't interact with the denied app directly.

114* **Code**: Claude auto-accepts file edits but still asks before running terminal commands. Use this when you trust file changes and want faster iteration.277* **Unhide apps when Claude finishes**: while Claude is working, your other windows are hidden so it interacts with only the approved app. When Claude finishes, hidden windows are restored unless you turn this setting off.

115* **Plan**: Claude creates a detailed plan for your approval before making any changes. Good for complex tasks where you want to review the approach first.

116 278 

117To stop Claude mid-task, click the stop button.279## Manage sessions

118 280 

119Remote sessions only support **Code** and **Plan** modes because they continue running in the background without requiring your active participation. See [permission modes](/en/iam#permission-modes) for details on how these work internally.281Each session is an independent conversation with its own context and changes. You can run multiple sessions in parallel, branch off side chats, send work to the cloud, or let Dispatch start sessions for you from your phone.

120 282 

121### Work in parallel with sessions283### Work in parallel with sessions

122 284 

123Click **+ New session** in the sidebar to work on multiple tasks in parallel. For Git repositories, each session gets its own isolated copy of your project using worktrees, so changes in one session don't affect another until you commit them. Worktrees are stored in `~/.claude-worktrees/` by default.285Click **+ New session** in the sidebar, or press **Cmd+N** on macOS or **Ctrl+N** on Windows, to work on multiple tasks in parallel. Press **Ctrl+Tab** and **Ctrl+Shift+Tab** to cycle through sessions in the sidebar. For Git repositories, each session gets its own isolated copy of your project using [Git worktrees](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees), so changes in one session don't affect other sessions until you commit them.

286 

287Worktrees are stored in `<project-root>/.claude/worktrees/` by default. You can change this to a custom directory in Settings → Claude Code under "Worktree location". You can also set a branch prefix that gets prepended to every worktree branch name, which is useful for keeping Claude-created branches organized. To remove a worktree when you're done, hover over the session in the sidebar and click the archive icon. To have sessions archive themselves when their pull request merges or closes, turn on **Auto-archive after PR merge or close** in Settings → Claude Code. Auto-archive only applies to local sessions that have finished running.

288 

289To include gitignored files like `.env` in new worktrees, create a [`.worktreeinclude` file](/en/common-workflows#copy-gitignored-files-to-worktrees) in your project root.

124 290 

125<Note>291<Note>

126 Session isolation requires [Git](https://git-scm.com/downloads). Without Git, sessions in the same directory edit the same files, so changes in one session are immediately visible in others.292 Session isolation requires [Git](https://git-scm.com/downloads). Most Macs include Git by default. Run `git --version` in Terminal to check. On Windows, Git is required for the Code tab to work: [download Git for Windows](https://git-scm.com/downloads/win), install it, and restart the app. If you run into Git errors, ask Claude in the [Cowork tab](https://claude.com/product/cowork) to help troubleshoot your setup.

127</Note>293</Note>

128 294 

129To include files listed in your `.gitignore` (like `.env`) in new worktrees, create a `.worktreeinclude` file in your project root listing the file patterns to copy.295Use the controls at the top of the sidebar to filter sessions by status, project, or environment, and to group sessions by project. To rename a session, click the session title in the toolbar at the top of the active session. To check context usage, see [Check usage](#check-usage). When context fills up, Claude automatically summarizes the conversation and continues working. You can also type `/compact` to trigger summarization earlier and free up context space. See [the context window](/en/how-claude-code-works#the-context-window) for details on how compaction works.

296 

297### Ask a side question without derailing the session

298 

299A side chat lets you ask Claude a question that uses your session's context but doesn't add anything back to the main conversation. Use it when you want to understand a piece of code, check an assumption, or explore an idea without steering the session off course.

300 

301Press **Cmd+;** on macOS or **Ctrl+;** on Windows to open a side chat, or type `/btw` in the prompt box. The side chat can read everything in the main thread up to that point. When you're done, close the side chat and continue the main session where you left off. Side chats are available in local and SSH sessions.

302 

303### Watch background tasks

130 304 

131To manage a session, click its dropdown in the sidebar to rename it, archive it, or check context usage. When context fills up, Claude automatically summarizes the conversation. You can also ask Claude to compact if you want to free up space earlier.305The tasks pane shows the background work running inside the current session: subagents, background shell commands, and workflows. Open it from the **Views** menu or drag it into your layout.

306 

307Click any entry to see its output in the subagent pane or stop it. To see what other sessions are doing, use the [sidebar](#work-in-parallel-with-sessions).

132 308 

133### Run long-running tasks remotely309### Run long-running tasks remotely

134 310 

135For large refactors, test suites, migrations, or other long-running tasks, select **Remote** instead of **Local** when starting a session. Remote sessions run on Anthropic's cloud infrastructure and continue even if you close the app or shut down your computer. Check back anytime to see progress or steer Claude in a different direction.311For large refactors, test suites, migrations, or other long-running tasks, select **Remote** instead of **Local** when starting a session. Remote sessions run on Anthropic's cloud infrastructure and continue even if you close the app or shut down your computer. Check back anytime to see progress or steer Claude in a different direction. You can also monitor remote sessions from [claude.ai/code](https://claude.ai/code) or the Claude iOS app.

136 312 

137Remote sessions support **Code** and **Plan** modes. See [Claude Code on the web](/en/claude-code-on-the-web) for details on configuring remote environments.313Remote sessions also support multiple repositories. After selecting a cloud environment, click the **+** button next to the repo pill to add additional repositories to the session. Each repo gets its own branch selector. This is useful for tasks that span multiple codebases, such as updating a shared library and its consumers.

138 314 

139### Review changes with diff view315See [Claude Code on the web](/en/claude-code-on-the-web) for more on how remote sessions work.

140 316 

141After Claude makes changes to your code, the diff view lets you review modifications file by file before creating a pull request.317### Continue in another surface

318 

319The **Continue in** menu, accessible from the VS Code icon in the bottom right of the session toolbar, lets you move your session to another surface:

320 

321* **Claude Code on the Web**: sends your local session to continue running remotely. Desktop pushes your branch, generates a summary of the conversation, and creates a new remote session with the full context. You can then choose to archive the local session or keep it. This requires a clean working tree, and is not available for SSH sessions.

322* **Your IDE**: opens your project in a supported IDE at the current working directory.

323 

324### Sessions from Dispatch

142 325 

143When Claude changes files, a diff stats indicator appears showing the number of lines added and removed (for example, `+12 -1`). Click this indicator to open the diff viewer, which displays a file list on the left and the changes for each file on the right.326[Dispatch](https://support.claude.com/en/articles/13947068) is a persistent conversation with Claude that lives in the [Cowork](https://claude.com/product/cowork#dispatch-and-computer-use) tab. You message Dispatch a task, and it decides how to handle it.

144 327 

145To comment on specific lines, click any line in the diff to open a comment box. Type your feedback and press **Enter** to send. In the full diff view, press **Enter** to accept each comment, then **Cmd+Enter** to send them all. Claude reads your comments and makes the requested changes, which appear as a new diff you can review.328A task can end up as a Code session in two ways: you ask for one directly, such as "open a Claude Code session and fix the login bug", or Dispatch decides the task is development work and spawns one on its own. Tasks that typically route to Code include fixing bugs, updating dependencies, running tests, or opening pull requests. Research, document editing, and spreadsheet work stay in Cowork.

329 

330Either way, the Code session appears in the Code tab's sidebar with a **Dispatch** badge. You get a push notification on your phone when it finishes or needs your approval.

331 

332If you have [computer use](#let-claude-use-your-computer) enabled, Dispatch-spawned Code sessions can use it too. App approvals in those sessions expire after 30 minutes and re-prompt, rather than lasting the full session like regular Code sessions.

333 

334For setup, pairing, and Dispatch settings, see the [Dispatch help article](https://support.claude.com/en/articles/13947068). Dispatch requires a Pro or Max plan and is not available on Team or Enterprise plans.

335 

336Dispatch is one of several ways to work with Claude when you're away from your terminal. See [Platforms and integrations](/en/platforms#work-when-you-are-away-from-your-terminal) to compare it with Remote Control, Channels, Slack, and scheduled tasks.

146 337 

147## Extend Claude Code338## Extend Claude Code

148 339 

149You can extend Claude Code with custom commands, automated workflows, and external integrations.340Connect external services, add reusable workflows, customize Claude's behavior, and configure preview servers. To manage connectors, skills, and plugins in one place, click **Customize** in the sidebar.

150 341 

151### Connect external tools342### Connect external tools

152 343 

153For local sessions, click the **...** button before starting and select **Connectors** to add integrations like Google Calendar, Slack, GitHub, Linear, Notion, and more. Connectors must be configured before the session starts and are only available for local sessions. Once connected, Claude can read your calendar, send messages, create issues, and interact with your tools directly. You can ask Claude what connectors are configured in your session.344For local and [SSH](#ssh-sessions) sessions, click the **+** button next to the prompt box and select **Connectors** to add integrations like Google Calendar, Slack, GitHub, Linear, Notion, and more. You can add connectors before or during a session. The **+** button is not available in remote sessions, but [routines](/en/routines) configure connectors at routine creation time.

345 

346To manage or disconnect connectors, go to Settings → Connectors in the desktop app, or select **Manage connectors** from the Connectors menu in the prompt box.

347 

348Once connected, Claude can read your calendar, send messages, create issues, and interact with your tools directly. You can ask Claude what connectors are configured in your session.

154 349 

155Connectors are [MCP (Model Context Protocol) servers](/en/mcp) with built-in setup. You can also [create custom connectors](https://support.claude.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp) or add MCP servers manually via [configuration files](/en/mcp#configure-mcp-servers).350Connectors are [MCP servers](/en/mcp) with a graphical setup flow. Use them for quick integration with supported services. For integrations not listed in Connectors, add MCP servers manually via [settings files](/en/mcp#installing-mcp-servers). You can also [create custom connectors](https://support.claude.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp).

156 351 

157### Create custom skills352### Use skills

158 353 

159[Skills](/en/skills) are reusable prompts that extend Claude's capabilities. For example, you could create a `review` skill that runs your standard code review checklist, or a `deploy` skill that walks through your deployment steps. Skills are defined as markdown files in `.claude/skills/` and can include instructions, context, and even call other tools. Ask Claude what skills are available or to run a specific skill. Claude can also help you create a skill if you describe what you want, or see [skills](/en/skills) to learn how to write them yourself.354[Skills](/en/skills) extend what Claude can do. Claude loads them automatically when relevant, or you can invoke one directly: type `/` in the prompt box or click the **+** button and select **Slash commands** to browse what's available. This includes [built-in commands](/en/commands), your [custom skills](/en/skills#create-your-first-skill), project skills from your codebase, and skills from any [installed plugins](/en/plugins). Select one and it appears highlighted in the input field. Type your task after it and send as usual.

160 355 

161### Automate workflows with hooks356### Install plugins

162 357 

163[Hooks](/en/hooks) run shell commands automatically in response to Claude Code events. For example, you could run a linter after every file edit, auto-format code, or send notifications when tasks complete. Hooks are configured in your [settings files](/en/settings). See [hooks](/en/hooks) for available events and configuration examples.358[Plugins](/en/plugins) are reusable packages that add skills, agents, hooks, MCP servers, and LSP configurations to Claude Code. You can install plugins from the desktop app without using the terminal.

359 

360For local and [SSH](#ssh-sessions) sessions, click the **+** button next to the prompt box and select **Plugins** to see your installed plugins and their skills. To add a plugin, select **Add plugin** from the submenu to open the plugin browser, which shows available plugins from your configured [marketplaces](/en/plugin-marketplaces) including the official Anthropic marketplace. Select **Manage plugins** to enable, disable, or uninstall plugins.

361 

362Plugins can be scoped to your user account, a specific project, or local-only. If your organization manages plugins centrally, those plugins are available in desktop sessions the same way they are in the CLI. Plugins are not available for remote sessions. For the full plugin reference including creating your own plugins, see [plugins](/en/plugins).

363 

364### Configure preview servers

365 

366Claude automatically detects your dev server setup and stores the configuration in `.claude/launch.json` at the root of the folder you selected when starting the session. Preview uses this folder as its working directory, so if you selected a parent folder, subfolders with their own dev servers won't be detected automatically. To work with a subfolder's server, either start a session in that folder directly or add a configuration manually.

367 

368To customize how your server starts, for example to use `yarn dev` instead of `npm run dev` or to change the port, edit the file manually or click **Edit configuration** in the Preview dropdown to open it in your code editor. The file supports JSON with comments.

369 

370```json theme={null}

371{

372 "version": "0.0.1",

373 "configurations": [

374 {

375 "name": "my-app",

376 "runtimeExecutable": "npm",

377 "runtimeArgs": ["run", "dev"],

378 "port": 3000

379 }

380 ]

381}

382```

383 

384You can define multiple configurations to run different servers from the same project, such as a frontend and an API. See the [examples](#examples) below.

385 

386#### Auto-verify changes

387 

388When `autoVerify` is enabled, Claude automatically verifies code changes after editing files. It takes screenshots, checks for errors, and confirms changes work before completing its response.

389 

390Auto-verify is on by default. Disable it per-project by adding `"autoVerify": false` to `.claude/launch.json`, or toggle it from the **Preview** dropdown menu.

391 

392```json theme={null}

393{

394 "version": "0.0.1",

395 "autoVerify": false,

396 "configurations": [...]

397}

398```

399 

400When disabled, preview tools are still available and you can ask Claude to verify at any time. Auto-verify makes it automatic after every edit.

401 

402#### Configuration fields

403 

404Each entry in the `configurations` array accepts the following fields:

405 

406| Field | Type | Description |

407| ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

408| `name` | string | A unique identifier for this server |

409| `runtimeExecutable` | string | The command to run, such as `npm`, `yarn`, or `node` |

410| `runtimeArgs` | string\[] | Arguments passed to `runtimeExecutable`, such as `["run", "dev"]` |

411| `port` | number | The port your server listens on. Defaults to 3000 |

412| `cwd` | string | Working directory relative to your project root. Defaults to the project root. Use `${workspaceFolder}` to reference the project root explicitly |

413| `env` | object | Additional environment variables as key-value pairs, such as `{ "NODE_ENV": "development" }`. Don't put secrets here since this file is committed to your repo. To pass secrets to your dev server, set them in the [local environment editor](#local-sessions) instead. |

414| `autoPort` | boolean | How to handle port conflicts. See below |

415| `program` | string | A script to run with `node`. See [when to use `program` vs `runtimeExecutable`](#when-to-use-program-vs-runtimeexecutable) |

416| `args` | string\[] | Arguments passed to `program`. Only used when `program` is set |

417 

418##### When to use `program` vs `runtimeExecutable`

419 

420Use `runtimeExecutable` with `runtimeArgs` to start a dev server through a package manager. For example, `"runtimeExecutable": "npm"` with `"runtimeArgs": ["run", "dev"]` runs `npm run dev`.

421 

422Use `program` when you have a standalone script you want to run with `node` directly. For example, `"program": "server.js"` runs `node server.js`. Pass additional flags with `args`.

423 

424#### Port conflicts

425 

426The `autoPort` field controls what happens when your preferred port is already in use:

427 

428* **`true`**: Claude finds and uses a free port automatically. Suitable for most dev servers.

429* **`false`**: Claude fails with an error. Use this when your server must use a specific port, such as for OAuth callbacks or CORS allowlists.

430* **Not set (default)**: Claude asks whether the server needs that exact port, then saves your answer.

431 

432When Claude picks a different port, it passes the assigned port to your server via the `PORT` environment variable.

433 

434#### Examples

435 

436These configurations show common setups for different project types:

437 

438<Tabs>

439 <Tab title="Next.js">

440 This configuration runs a Next.js app using Yarn on port 3000:

441 

442 ```json theme={null}

443 {

444 "version": "0.0.1",

445 "configurations": [

446 {

447 "name": "web",

448 "runtimeExecutable": "yarn",

449 "runtimeArgs": ["dev"],

450 "port": 3000

451 }

452 ]

453 }

454 ```

455 </Tab>

456 

457 <Tab title="Multiple servers">

458 For a monorepo with a frontend and an API server, define multiple configurations. The frontend uses `autoPort: true` so it picks a free port if 3000 is taken, while the API server requires port 8080 exactly:

459 

460 ```json theme={null}

461 {

462 "version": "0.0.1",

463 "configurations": [

464 {

465 "name": "frontend",

466 "runtimeExecutable": "npm",

467 "runtimeArgs": ["run", "dev"],

468 "cwd": "apps/web",

469 "port": 3000,

470 "autoPort": true

471 },

472 {

473 "name": "api",

474 "runtimeExecutable": "npm",

475 "runtimeArgs": ["run", "start"],

476 "cwd": "server",

477 "port": 8080,

478 "env": { "NODE_ENV": "development" },

479 "autoPort": false

480 }

481 ]

482 }

483 ```

484 </Tab>

485 

486 <Tab title="Node.js script">

487 To run a Node.js script directly instead of using a package manager command, use the `program` field:

488 

489 ```json theme={null}

490 {

491 "version": "0.0.1",

492 "configurations": [

493 {

494 "name": "server",

495 "program": "server.js",

496 "args": ["--verbose"],

497 "port": 4000

498 }

499 ]

500 }

501 ```

502 </Tab>

503</Tabs>

164 504 

165## Environment configuration505## Environment configuration

166 506 

167When starting a session, you choose between **Local** (runs on your machine) or **Remote** (runs on Anthropic's cloud).507The environment you pick when [starting a session](#start-a-session) determines where Claude executes and how you connect:

508 

509* **Local**: runs on your machine with direct access to your files

510* **Remote**: runs on Anthropic's cloud infrastructure. Sessions continue even if you close the app.

511* **SSH**: runs on a remote machine you connect to over SSH, such as your own servers, cloud VMs, or dev containers

512 

513### Local sessions

514 

515The desktop app does not always inherit your full shell environment. On macOS, when you launch the app from the Dock or Finder, it reads your shell profile, such as `~/.zshrc` or `~/.bashrc`, to extract `PATH` and a fixed set of Claude Code variables, but other variables you export there are not picked up. On Windows, the app inherits user and system environment variables but does not read PowerShell profiles.

516 

517To set environment variables for local sessions and dev servers on any platform, open the environment dropdown in the prompt box, hover over **Local**, and click the gear icon to open the local environment editor. Variables you save here are stored encrypted on your machine and apply to every local session and preview server you start. You can also add variables to the `env` key in your `~/.claude/settings.json` file, though these reach Claude sessions only and not dev servers. See [environment variables](/en/env-vars) for the full list of supported variables.

168 518 

169**Local sessions** inherit environment variables from your shell. If you need additional variables, set them in your shell profile (`~/.zshrc`, `~/.bashrc`) and restart the desktop app. See [environment variables](/en/settings#environment-variables) for the full list of supported variables.519[Extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) is enabled by default, which improves performance on complex reasoning tasks but uses additional tokens. To disable thinking entirely, set `MAX_THINKING_TOKENS` to `0` in the local environment editor. On models with [adaptive reasoning](/en/model-config#adjust-effort-level), any other `MAX_THINKING_TOKENS` value is ignored because adaptive reasoning controls thinking depth instead. On Opus 4.6 and Sonnet 4.6, set `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` to `1` to use a fixed thinking budget; Opus 4.7 always uses adaptive reasoning and has no fixed-budget mode.

170 520 

171[Extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) is enabled by default, which improves performance on complex reasoning tasks but uses additional tokens. The thinking process runs in the background but isn't displayed in the Desktop interface. To disable it or adjust the budget, set `MAX_THINKING_TOKENS` in your shell profile (use `0` to disable).521### Remote sessions

172 522 

173**Remote sessions** run on Anthropic's cloud infrastructure and continue even if you close the app. Usage counts toward your subscription plan limits with no separate compute charges. See [Claude Code on the web](/en/claude-code-on-the-web) for details on configuring remote environments.523Remote sessions continue in the background even if you close the app. Usage counts toward your [subscription plan limits](/en/costs) with no separate compute charges.

174 524 

175## How Desktop relates to CLI525You can create custom cloud environments with different network access levels and environment variables. Select the environment dropdown when starting a remote session and choose **Add environment**. See [the cloud environment](/en/claude-code-on-the-web#the-cloud-environment) for details on configuring network access and environment variables.

526 

527### SSH sessions

528 

529SSH sessions let you run Claude Code on a remote machine while using the desktop app as your interface. This is useful for working with codebases that live on cloud VMs, dev containers, or servers with specific hardware or dependencies.

530 

531To add an SSH connection, click the environment dropdown before starting a session and select **+ Add SSH connection**. The dialog asks for:

532 

533* **Name**: a friendly label for this connection

534* **SSH Host**: `user@hostname` or a host defined in `~/.ssh/config`

535* **SSH Port**: defaults to 22 if left empty, or uses the port from your SSH config

536* **Identity File**: path to your private key, such as `~/.ssh/id_rsa`. Leave empty to use the default key or your SSH config.

537 

538Once added, the connection appears in the environment dropdown. Select it to start a session on that machine. Claude runs on the remote machine with access to its files and tools.

539 

540The remote machine must run Linux or macOS. Desktop installs Claude Code on the remote machine automatically the first time you connect. Once connected, SSH sessions support permission modes, connectors, plugins, and MCP servers.

541 

542#### Pre-configure SSH connections for your team

543 

544Administrators can distribute SSH connections to team members by adding `sshConfigs` to a [managed settings](/en/settings#settings-precedence) file. Connections defined this way appear in each user's environment dropdown automatically and are shown as managed, so users can select them but cannot edit or delete them in the app.

545 

546The following example pre-configures a single connection that opens in `~/projects` on the remote host:

547 

548```json theme={null}

549{

550 "sshConfigs": [

551 {

552 "id": "shared-dev-vm",

553 "name": "Shared Dev VM",

554 "sshHost": "user@dev.example.com",

555 "sshPort": 22,

556 "sshIdentityFile": "~/.ssh/id_ed25519",

557 "startDirectory": "~/projects"

558 }

559 ]

560}

561```

176 562 

177If you already use the Claude Code CLI, Desktop runs the same underlying engine with a graphical interface. You can run both simultaneously on the same machine, even on the same project. Each maintains separate session history, but they share configuration and project memory (CLAUDE.md files).563Each entry requires `id`, `name`, and `sshHost`. The `sshPort`, `sshIdentityFile`, and `startDirectory` fields are optional. Users can also add `sshConfigs` to their own `~/.claude/settings.json`, which is where connections added through the dialog are stored.

564 

565## Enterprise configuration

566 

567Organizations on Team or Enterprise plans can manage desktop app behavior through admin console controls, managed settings files, and device management policies.

568 

569### Admin console controls

570 

571These settings are configured through the [admin settings console](https://claude.ai/admin-settings/claude-code):

572 

573* **Code in the desktop**: control whether users in your organization can access Claude Code in the desktop app

574* **Code in the web**: enable or disable [web sessions](/en/claude-code-on-the-web) for your organization

575* **Remote Control**: enable or disable [Remote Control](/en/remote-control) for your organization

576* **Disable Bypass permissions mode**: prevent users in your organization from enabling bypass permissions mode

577 

578### Managed settings

579 

580Managed settings override project and user settings and apply when Desktop spawns CLI sessions. You can set these keys in your organization's [managed settings](/en/settings#settings-precedence) file or push them remotely through the admin console.

581 

582| Key | Description |

583| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

584| `permissions.disableBypassPermissionsMode` | set to `"disable"` to prevent users from enabling Bypass permissions mode. |

585| `disableAutoMode` | set to `"disable"` to prevent users from enabling [Auto](/en/permission-modes#eliminate-prompts-with-auto-mode) mode. Removes Auto from the mode selector. Also accepted under `permissions`. |

586| `autoMode` | customize what the auto mode classifier trusts and blocks across your organization. See [Configure auto mode](/en/auto-mode-config). |

587| `sshConfigs` | pre-configure [SSH connections](#pre-configure-ssh-connections-for-your-team) that appear in the environment dropdown. Users cannot edit or delete managed connections. |

588 

589A managed settings file deployed to disk on each machine applies to Desktop sessions. Managed settings pushed remotely through the admin console currently reach CLI and IDE sessions only, so for Desktop deployments either distribute the file via MDM or use the [admin console controls](#admin-console-controls) above.

590 

591`permissions.disableBypassPermissionsMode` and `disableAutoMode` also work in user and project settings, but placing them in managed settings prevents users from overriding them. `autoMode` is read from user settings, `.claude/settings.local.json`, and managed settings, but not from the checked-in `.claude/settings.json`: a cloned repo cannot inject its own classifier rules. For the complete list of managed-only settings including `allowManagedPermissionRulesOnly` and `allowManagedHooksOnly`, see [managed-only settings](/en/permissions#managed-only-settings).

592 

593### Device management policies

594 

595IT teams can manage the desktop app through MDM on macOS or group policy on Windows. Available policies include enabling or disabling the Claude Code feature, controlling auto-updates, and setting a custom deployment URL.

596 

597* **macOS**: configure via `com.anthropic.Claude` preference domain using tools like Jamf or Kandji

598* **Windows**: configure via registry at `SOFTWARE\Policies\Claude`

599 

600### Authentication and SSO

601 

602Enterprise organizations can require SSO for all users. See [authentication](/en/authentication) for plan-level details and [Setting up SSO](https://support.claude.com/en/articles/13132885-setting-up-single-sign-on-sso) for SAML and OIDC configuration.

603 

604### Data handling

605 

606Claude Code processes your code locally in local sessions or on Anthropic's cloud infrastructure in remote sessions. Conversations and code context are sent to Anthropic's API for processing. See [data handling](/en/data-usage) for details on data retention, privacy, and compliance.

607 

608### Deployment

609 

610Desktop can be distributed through enterprise deployment tools:

611 

612* **macOS**: distribute via MDM such as Jamf or Kandji using the `.dmg` installer

613* **Windows**: deploy via MSIX package or `.exe` installer. See [Deploy Claude Desktop for Windows](https://support.claude.com/en/articles/12622703-deploy-claude-desktop-for-windows) for enterprise deployment options including silent installation

614 

615For network configuration such as proxy settings, firewall allowlisting, and LLM gateways, see [network configuration](/en/network-config).

616 

617For the full enterprise configuration reference, see the [enterprise configuration guide](https://support.claude.com/en/articles/12622667-enterprise-configuration).

618 

619## Coming from the CLI?

620 

621If you already use the Claude Code CLI, Desktop runs the same underlying engine with a graphical interface. You can run both simultaneously on the same machine, even on the same project. Each maintains separate session history, but they share configuration and project memory via CLAUDE.md files.

622 

623To move a CLI session into Desktop, run `/desktop` in the terminal. Claude saves your session and opens it in the desktop app, then exits the CLI. This command is available on macOS and Windows only.

624 

625<Tip>

626 When to use Desktop vs CLI: use Desktop when you want to manage parallel sessions in one window, arrange panes side by side, or review changes visually. Use the CLI when you need scripting, automation, or prefer a terminal workflow.

627</Tip>

178 628 

179### CLI flag equivalents629### CLI flag equivalents

180 630 

181If you're used to CLI flags, the table below shows the Desktop equivalent for each. Some flags have no Desktop equivalent because they're designed for scripting or automation.631This table shows the desktop app equivalent for common CLI flags. Flags not listed have no desktop equivalent because they are designed for scripting or automation.

182 632 

183| CLI | Desktop equivalent |633| CLI | Desktop equivalent |

184| ------------------------------------- | ---------------------------------------------- |634| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |

185| `--model sonnet` | **...** menu > Model (before starting session) |635| `--model sonnet` | Model dropdown next to the send button |

186| `--resume`, `--continue` | Click a session in the sidebar |636| `--resume`, `--continue` | Click a session in the sidebar |

187| `--allowedTools`, `--disallowedTools` | Not available in Desktop |637| `--permission-mode` | Mode selector next to the send button |

188| `--dangerously-skip-permissions` | Not available in Desktop |638| `--dangerously-skip-permissions` | Bypass permissions mode. Enable in Settings → Claude Code → "Allow bypass permissions mode". Enterprise admins can disable this setting. |

189| `--print` | Not available (Desktop is interactive) |639| `--add-dir` | Add multiple repos with the **+** button in remote sessions |

640| `--allowedTools`, `--disallowedTools` | No per-session equivalent. Permission rules in [settings files](/en/settings) still apply. |

641| `--verbose` | [Verbose view mode](#switch-view-modes) in the Transcript view dropdown |

642| `--print`, `--output-format` | Not available. Desktop is interactive only. |

643| `ANTHROPIC_MODEL` env var | Model dropdown next to the send button |

644| `MAX_THINKING_TOKENS` env var | Set in the local environment editor. See [environment configuration](#environment-configuration). |

190 645 

191### Shared configuration646### Shared configuration

192 647 

193Desktop and CLI read the same configuration files, so your setup carries over:648Desktop and CLI read the same configuration files, so your setup carries over:

194 649 

195* **[CLAUDE.md](/en/memory)** and **CLAUDE.local.md** files in your project are used by both650* **[CLAUDE.md](/en/memory)** and `CLAUDE.local.md` files in your project are used by both

196* **[MCP servers](/en/mcp)** configured in `~/.claude.json` or `.mcp.json` work in both651* **[MCP servers](/en/mcp)** configured in `~/.claude.json` or `.mcp.json` work in both

197* **[Hooks](/en/hooks)** and **[skills](/en/skills)** defined in settings apply to both652* **[Hooks](/en/hooks)** and **[skills](/en/skills)** defined in settings apply to both

198* **[Settings](/en/settings)** in `~/.claude.json` and `~/.claude/settings.json` are shared653* **[Settings](/en/settings)** in `~/.claude.json` and `~/.claude/settings.json` are shared. Permission rules, allowed tools, and other settings in `settings.json` apply to Desktop sessions.

199* **Models** (Sonnet, Opus, Haiku) are available in both (Desktop requires selecting before starting a session)654* **Models**: Sonnet, Opus, and Haiku are available in both. In Desktop, select the model from the dropdown next to the send button. You can change the model mid-session from the same dropdown.

200 655 

201<Note>656<Note>

202 MCP servers configured for the **Claude Desktop chat app** (in `claude_desktop_config.json`) are separate from Claude Code. To use MCP servers in Claude Code, configure them in `~/.claude.json` or your project's `.mcp.json` file. See [MCP configuration](/en/mcp#configure-mcp-servers) for details.657 **MCP servers: desktop chat app vs Claude Code**: MCP servers configured for the Claude Desktop chat app in `claude_desktop_config.json` are separate from Claude Code and will not appear in the Code tab. To use MCP servers in Claude Code, configure them in `~/.claude.json` or your project's `.mcp.json` file. See [MCP configuration](/en/mcp#installing-mcp-servers) for details.

203</Note>658</Note>

204 659 

205### What's different660### Feature comparison

661 

662This table compares core capabilities between the CLI and Desktop. For a full list of CLI flags, see the [CLI reference](/en/cli-reference).

206 663 

207**Desktop adds:**664| Feature | CLI | Desktop |

665| ----------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

666| Permission modes | All modes including `dontAsk` | Ask permissions, Auto accept edits, Plan mode, Auto, and Bypass permissions via Settings |

667| `--dangerously-skip-permissions` | CLI flag | Bypass permissions mode. Enable in Settings → Claude Code → "Allow bypass permissions mode" |

668| [Third-party providers](/en/third-party-integrations) | Bedrock, Vertex, Foundry | Anthropic's API by default. Enterprise deployments can configure Vertex AI and gateway providers. See the [enterprise configuration guide](https://support.claude.com/en/articles/12622667-enterprise-configuration). |

669| [MCP servers](/en/mcp) | Configure in settings files | Connectors UI for local and SSH sessions, or settings files |

670| [Plugins](/en/plugins) | `/plugin` command | Plugin manager UI |

671| @mention files | Text-based | With autocomplete; local and SSH sessions only |

672| File attachments | Not available | Images, PDFs |

673| Session isolation | [`--worktree`](/en/cli-reference) flag | Automatic worktrees |

674| Multiple sessions | Separate terminals | Sidebar tabs |

675| Recurring tasks | Cron jobs, CI pipelines | [Scheduled tasks](/en/desktop-scheduled-tasks) |

676| Computer use | [Enable via `/mcp`](/en/computer-use) on macOS | [App and screen control](#let-claude-use-your-computer) on macOS and Windows |

677| Dispatch integration | Not available | [Dispatch sessions](#sessions-from-dispatch) in the sidebar |

678| Scripting and automation | [`--print`](/en/cli-reference), [Agent SDK](/en/headless) | Not available |

208 679 

209* Graphical interface with visual session management680### What's not available in Desktop

210* Built-in connectors for common integrations

211* Automatic session isolation for Git repositories (each session gets its own worktree)

212 681 

213**CLI adds:**682The following features are only available in the CLI or VS Code extension:

214 683 

215* [Third-party API providers](/en/third-party-integrations) (Bedrock, Vertex, Foundry). If you use these, continue using CLI for those projects.684* **Third-party providers**: Desktop connects to Anthropic's API by default. Enterprise deployments can configure Vertex AI and gateway providers via [managed settings](https://support.claude.com/en/articles/12622667-enterprise-configuration). For Bedrock or Foundry, use the [CLI](/en/quickstart).

216* [CLI flags](/en/cli-reference) for scripting (`--print`, `--resume`, `--continue`)685* **Linux**: the desktop app is available on macOS and Windows only.

217* [Programmatic usage](/en/headless) via the Agent SDK686* **Inline code suggestions**: Desktop does not provide autocomplete-style suggestions. It works through conversational prompts and explicit code changes.

687* **Agent teams**: multi-agent orchestration is available via the [CLI](/en/agent-teams) and [Agent SDK](/en/headless), not in Desktop.

218 688 

219## Troubleshooting689## Troubleshooting

220 690 

221Solutions to common issues with the Claude desktop app. For CLI issues, see [CLI troubleshooting](/en/troubleshooting).691The sections below cover issues specific to the desktop app. For runtime API errors that appear in the chat such as `API Error: 500`, `529 Overloaded`, `429`, or `Prompt is too long`, see the [Error reference](/en/errors). Those errors and their fixes are the same across the CLI, desktop, and web.

222 692 

223### Check your version693### Check your version

224 694 

225To see which version of the desktop app you're running:695To see which version of the desktop app you're running:

226 696 

227* **macOS**: Click **Claude** in the menu bar, then **About Claude**697* **macOS**: click **Claude** in the menu bar, then **About Claude**

228* **Windows**: Click **Help**, then **About**698* **Windows**: click **Help**, then **About**

229 699 

230Click the version number to copy it to your clipboard.700Click the version number to copy it to your clipboard.

231 701 

232### "Branch doesn't exist yet" when opening in CLI702### 403 or authentication errors in the Code tab

233 703 

234Remote sessions can create branches that don't exist on your local machine. Click the branch name in the session toolbar to copy it, then fetch it locally:704If you see `Error 403: Forbidden` or other authentication failures when using the Code tab:

235 705 

236```bash theme={null}7061. Sign out and back in from the app menu. This is the most common fix.

237git fetch origin <branch-name>7072. Verify you have an active paid subscription: Pro, Max, Team, or Enterprise.

238git checkout <branch-name>7083. If the CLI works but Desktop does not, quit the desktop app completely, not just close the window, then reopen and sign in again.

239```7094. Check your internet connection and proxy settings.

240 710 

241### "Failed to load session" error711### Blank or stuck screen on launch

242 712 

243This error can occur for several reasons:713If the app opens but shows a blank or unresponsive screen:

244 714 

245* The selected folder no longer exists or is inaccessible7151. Restart the app.

246* A Git repository requires Git LFS but it's not installed (see [Git LFS errors](#git-lfs-errors))7162. Check for pending updates. The app auto-updates on launch.

247* File permissions prevent access to the project directory7173. On Windows, check Event Viewer for crash logs under **Windows Logs → Application**.

248 718 

249Try selecting a different folder or restarting the desktop app.719### "Failed to load session"

250 720 

251### App won't quit721If you see `Failed to load session`, the selected folder may no longer exist, a Git repository may require Git LFS that isn't installed, or file permissions may prevent access. Try selecting a different folder or restarting the app.

252 722 

253If the desktop app doesn't close properly:723### Session not finding installed tools

254 

255* **macOS**: Press Cmd+Q. If the app doesn't respond, use Force Quit (Cmd+Option+Esc, select Claude, click Force Quit).

256* **Windows**: Use Task Manager (Ctrl+Shift+Esc) to end the Claude process.

257 724 

258### Windows installation issues725If Claude can't find tools like `npm`, `node`, or other CLI commands, verify the tools work in your regular terminal, check that your shell profile properly sets up PATH, and restart the desktop app to reload environment variables.

259 726 

260If the installer fails silently or doesn't complete properly:727### Git and Git LFS errors

261 728 

2621. **PATH not updated**: After installation, open a new terminal window. The PATH updates only apply to new terminal sessions.729On Windows, Git is required for the Code tab to start local sessions. If you see "Git is required," install [Git for Windows](https://git-scm.com/downloads/win) and restart the app.

2632. **Concurrent installation error**: If you see an error about another installation in progress but there isn't one, try running the installer as Administrator.

264 730 

265### Session not finding installed tools731If you see "Git LFS is required by this repository but is not installed," install Git LFS from [git-lfs.com](https://git-lfs.com/), run `git lfs install`, and restart the app.

266 732 

267If Claude can't find tools like `npm`, `node`, or other CLI commands:733### MCP servers not working on Windows

268 734 

2691. Verify the tools work in your regular terminal735If MCP server toggles don't respond or servers fail to connect on Windows, check that the server is properly configured in your settings, restart the app, verify the server process is running in Task Manager, and review server logs for connection errors.

2702. Check that your shell profile (`~/.zshrc`, `~/.bashrc`) properly sets up PATH

2713. Restart the desktop app to reload environment variables

272 736 

273### MCP servers not working (Windows)737### App won't quit

274 738 

275If MCP server toggles don't respond or servers fail to connect on Windows:739* **macOS**: press Cmd+Q. If the app doesn't respond, use Force Quit with Cmd+Option+Esc, select Claude, and click Force Quit.

740* **Windows**: use Task Manager with Ctrl+Shift+Esc to end the Claude process.

276 741 

2771. Check that the MCP server is properly configured in your settings742### Windows-specific issues

2782. Restart the desktop app after making changes

2793. Verify the MCP server process is running (check Task Manager)

2804. Review the server logs for connection errors

281 743 

282### Git LFS errors744* **PATH not updated after install**: open a new terminal window. PATH updates only apply to new terminal sessions.

745* **Concurrent installation error**: if you see an error about another installation in progress but there isn't one, try running the installer as Administrator.

283 746 

284If you see "Git LFS is required by this repository but is not installed," your repository uses Git Large File Storage for large binary files. Install Git LFS before opening this repository:747### "Branch doesn't exist yet" when opening in CLI

285 748 

2861. Install Git LFS from [git-lfs.com](https://git-lfs.com/)749Remote sessions can create branches that don't exist on your local machine. Click the branch name in the session toolbar to copy it, then fetch it locally:

2872. Run `git lfs install` in your terminal

2883. Restart the desktop app

289 750 

290## Enterprise configuration751```bash theme={null}

752git fetch origin <branch-name>

753git checkout <branch-name>

754```

291 755 

292Organizations can disable local Claude Code use in the desktop application with the `isClaudeCodeForDesktopEnabled` [enterprise policy option](https://support.claude.com/en/articles/12622667-enterprise-configuration#h_003283c7cb). Additionally, Claude Code on the web can be disabled in your [admin settings](https://claude.ai/admin-settings/claude-code).756### Still stuck?

293 757 

294## Related resources758* Search or file a bug on [GitHub Issues](https://github.com/anthropics/claude-code/issues)

759* Visit the [Claude support center](https://support.claude.com/)

295 760 

296* [Claude Code on the web](/en/claude-code-on-the-web): Run remote sessions that continue in the cloud761When filing a bug, include your desktop app version, your operating system, the exact error message, and relevant logs. On macOS, check Console.app. On Windows, check Event Viewer → Windows Logs → Application.

297* [CLI reference](/en/cli-reference): Use Claude Code in your terminal with flags and scripting

298* [Common workflows](/en/common-workflows): Tutorials for debugging, refactoring, testing, and more

299* [Settings reference](/en/settings): Configure Claude Code behavior with settings files

300* [Claude Desktop support](https://support.claude.com/en/collections/16163169-claude-desktop): Help articles for the Chat tab and general desktop app usage

301* [Enterprise configuration](https://support.claude.com/en/articles/12622667-enterprise-configuration): Admin policies for organizational deployments

desktop-quickstart.md +129 −0 added

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# Get started with the desktop app

6 

7> Install Claude Code on desktop and start your first coding session

8 

9The desktop app gives you Claude Code with a graphical interface built for running multiple sessions side by side: a sidebar for managing parallel work, a drag-and-drop layout with an integrated terminal and file editor, visual diff review, live app preview, GitHub PR monitoring with auto-merge, and scheduled tasks. No terminal required.

10 

11<CardGroup cols={2}>

12 <Card title="Download for macOS" icon="apple" href="https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code&utm_medium=docs">

13 Universal build for Intel and Apple Silicon

14 </Card>

15 

16 <Card title="Download for Windows" icon="windows" href="https://claude.ai/api/desktop/win32/x64/setup/latest/redirect?utm_source=claude_code&utm_medium=docs">

17 For x64 processors

18 </Card>

19</CardGroup>

20 

21For Windows ARM64, download the [ARM64 installer](https://claude.ai/api/desktop/win32/arm64/setup/latest/redirect?utm_source=claude_code\&utm_medium=docs). Linux is not supported.

22 

23<Note>

24 Claude Code requires a [Pro, Max, Team, or Enterprise subscription](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=desktop_quickstart_pricing).

25</Note>

26 

27This page walks through installing the app and starting your first session. If you're already set up, see [Use Claude Code Desktop](/en/desktop) for the full reference.

28 

29The desktop app has three tabs:

30 

31* **Chat**: General conversation with no file access, similar to claude.ai.

32* **Cowork**: An autonomous background agent that works on tasks in a cloud VM with its own environment. It can run independently while you do other work.

33* **Code**: An interactive coding assistant with direct access to your local files. You review and approve each change in real time.

34 

35Chat and Cowork are covered in the [Claude Desktop support articles](https://support.claude.com/en/collections/16163169-claude-desktop). This page focuses on the **Code** tab.

36 

37## Install

38 

39<Steps>

40 <Step title="Install and sign in">

41 Download the installer for your platform from the links above and run it. Launch Claude from your Applications folder on macOS or the Start menu on Windows, then sign in with your Anthropic account.

42 </Step>

43 

44 <Step title="Open the Code tab">

45 Click the **Code** tab at the top center. If clicking Code prompts you to upgrade, you need to [subscribe to a paid plan](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=desktop_quickstart_upgrade) first. If it prompts you to sign in online, complete the sign-in and restart the app. If you see a 403 error, see [authentication troubleshooting](/en/desktop#403-or-authentication-errors-in-the-code-tab).

46 </Step>

47</Steps>

48 

49The desktop app includes Claude Code. You don't need to install Node.js or the CLI separately. To use `claude` from the terminal, install the CLI separately. See [Get started with the CLI](/en/quickstart).

50 

51## Start your first session

52 

53With the Code tab open, choose a project and give Claude something to do.

54 

55<Steps>

56 <Step title="Choose an environment and folder">

57 Select **Local** to run Claude on your machine using your files directly. Click **Select folder** and choose your project directory.

58 

59 <Tip>

60 Start with a small project you know well. It's the fastest way to see what Claude Code can do. On Windows, [Git](https://git-scm.com/downloads/win) must be installed for local sessions to work. Most Macs include Git by default.

61 </Tip>

62 

63 You can also select:

64 

65 * **Remote**: Run sessions on Anthropic's cloud infrastructure that continue even if you close the app. Remote sessions use the same infrastructure as [Claude Code on the web](/en/claude-code-on-the-web).

66 * **SSH**: Connect to a remote machine over SSH, such as your own servers, cloud VMs, or dev containers. Desktop installs Claude Code on the remote machine automatically the first time you connect.

67 </Step>

68 

69 <Step title="Choose a model">

70 Select a model from the dropdown next to the send button. See [models](/en/model-config#available-models) for a comparison of Opus, Sonnet, and Haiku. You can change the model later from the same dropdown.

71 </Step>

72 

73 <Step title="Tell Claude what to do">

74 Type what you want Claude to do:

75 

76 * `Find a TODO comment and fix it`

77 * `Add tests for the main function`

78 * `Create a CLAUDE.md with instructions for this codebase`

79 

80 A [session](/en/desktop#work-in-parallel-with-sessions) is a conversation with Claude about your code. Each session tracks its own context and changes, so you can work on multiple tasks without them interfering with each other.

81 </Step>

82 

83 <Step title="Review and accept changes">

84 By default, the Code tab starts in [Ask permissions mode](/en/desktop#choose-a-permission-mode), where Claude proposes changes and waits for your approval before applying them. You'll see:

85 

86 1. A [diff view](/en/desktop#review-changes-with-diff-view) showing exactly what will change in each file

87 2. Accept/Reject buttons to approve or decline each change

88 3. Real-time updates as Claude works through your request

89 

90 If you reject a change, Claude will ask how you'd like to proceed differently. Your files aren't modified until you accept.

91 </Step>

92</Steps>

93 

94## Now what?

95 

96You've made your first edit. For the full reference on everything Desktop can do, see [Use Claude Code Desktop](/en/desktop). Here are some things to try next.

97 

98**Interrupt and steer.** You can interrupt Claude at any point. If it's going down the wrong path, click the stop button or type your correction and press **Enter**. Claude stops what it's doing and adjusts based on your input. You don't have to wait for it to finish or start over.

99 

100**Give Claude more context.** Type `@filename` in the prompt box to pull a specific file into the conversation, attach images and PDFs using the attachment button, or drag and drop files directly into the prompt. The more context Claude has, the better the results. See [Add files and context](/en/desktop#add-files-and-context-to-prompts).

101 

102**Use skills for repeatable tasks.** Type `/` or click **+** → **Slash commands** to browse [built-in commands](/en/commands), [custom skills](/en/skills), and plugin skills. Skills are reusable prompts you can invoke whenever you need them, like code review checklists or deployment steps.

103 

104**Review changes before committing.** After Claude edits files, a `+12 -1` indicator appears. Click it to open the [diff view](/en/desktop#review-changes-with-diff-view), review modifications file by file, and comment on specific lines. Claude reads your comments and revises. Click **Review code** to have Claude evaluate the diffs itself and leave inline suggestions.

105 

106**Adjust how much control you have.** Your [permission mode](/en/desktop#choose-a-permission-mode) controls the balance. Ask permissions (default) requires approval before every edit. Auto accept edits auto-accepts file edits for faster iteration. Plan mode lets Claude map out an approach without touching any files, which is useful before a large refactor.

107 

108**Add plugins for more capabilities.** Click the **+** button next to the prompt box and select **Plugins** to browse and install [plugins](/en/desktop#install-plugins) that add skills, agents, MCP servers, and more.

109 

110**Arrange your workspace.** Drag the chat, diff, terminal, file, and preview panes into whatever layout you want. Open the terminal with **Ctrl+\`** to run commands alongside your session, or click a file path to open it in the file pane. See [Arrange your workspace](/en/desktop#arrange-your-workspace).

111 

112**Preview your app.** Click the **Preview** dropdown to run your dev server directly in the desktop. Claude can view the running app, test endpoints, inspect logs, and iterate on what it sees. See [Preview your app](/en/desktop#preview-your-app).

113 

114**Track your pull request.** After opening a PR, Claude Code monitors CI check results and can automatically fix failures or merge the PR once all checks pass. See [Monitor pull request status](/en/desktop#monitor-pull-request-status).

115 

116**Put Claude on a schedule.** Set up [scheduled tasks](/en/desktop-scheduled-tasks) to run Claude automatically on a recurring basis: a daily code review every morning, a weekly dependency audit, or a briefing that pulls from your connected tools.

117 

118**Scale up when you're ready.** Open [parallel sessions](/en/desktop#work-in-parallel-with-sessions) from the sidebar to work on multiple tasks at once, each in its own Git worktree, and open the [tasks pane](/en/desktop#watch-background-tasks) to watch the subagents and background commands a session has running. Open a [side chat](/en/desktop#ask-a-side-question-without-derailing-the-session) to ask a question without derailing the main thread. Send [long-running work to the cloud](/en/desktop#run-long-running-tasks-remotely) so it continues even if you close the app, or [continue a session on the web or in your IDE](/en/desktop#continue-in-another-surface) if a task takes longer than expected. [Connect external tools](/en/desktop#extend-claude-code) like GitHub, Slack, and Linear to bring your workflow together.

119 

120## Coming from the CLI?

121 

122Desktop runs the same engine as the CLI with a graphical interface. You can run both simultaneously on the same project, and they share configuration (CLAUDE.md files, MCP servers, hooks, skills, and settings). For a full comparison of features, flag equivalents, and what's not available in Desktop, see [CLI comparison](/en/desktop#coming-from-the-cli).

123 

124## What's next

125 

126* [Use Claude Code Desktop](/en/desktop): permission modes, parallel sessions, diff view, connectors, and enterprise configuration

127* [Troubleshooting](/en/desktop#troubleshooting): solutions to common errors and setup issues

128* [Best practices](/en/best-practices): tips for writing effective prompts and getting the most out of Claude Code

129* [Common workflows](/en/common-workflows): tutorials for debugging, refactoring, testing, and more

desktop-scheduled-tasks.md +104 −0 added

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# Schedule recurring tasks in Claude Code Desktop

6 

7> Set up scheduled tasks in Claude Code Desktop to run Claude automatically on a recurring basis for daily code reviews, dependency audits, or morning briefings.

8 

9Scheduled tasks start a new session automatically at a time and frequency you choose. Use them for recurring work like daily code reviews, dependency update checks, or morning briefings that pull from your calendar and inbox.

10 

11The Desktop app's **Routines** page lets you create both local scheduled tasks and remote [routines](/en/routines). A local task runs on your machine with direct access to your files and tools, but only fires while the app is open and your computer is awake. A remote routine runs on Anthropic-managed cloud infrastructure even when your computer is off, and can also fire on API calls or GitHub events. This page covers local scheduled tasks; for remote routines and their trigger options, see [Routines](/en/routines).

12 

13## Compare scheduling options

14 

15Claude Code offers three ways to schedule recurring or one-off work:

16 

17| | [Cloud](/en/routines) | [Desktop](/en/desktop-scheduled-tasks) | [`/loop`](/en/scheduled-tasks) |

18| :------------------------- | :----------------------------- | :------------------------------------- | :---------------------------------- |

19| Runs on | Anthropic cloud | Your machine | Your machine |

20| Requires machine on | No | Yes | Yes |

21| Requires open session | No | No | Yes |

22| Persistent across restarts | Yes | Yes | Restored on `--resume` if unexpired |

23| Access to local files | No (fresh clone) | Yes | Yes |

24| MCP servers | Connectors configured per task | [Config files](/en/mcp) and connectors | Inherits from session |

25| Permission prompts | No (runs autonomously) | Configurable per task | Inherits from session |

26| Customizable schedule | Via `/schedule` in the CLI | Yes | Yes |

27| Minimum interval | 1 hour | 1 minute | 1 minute |

28 

29<Tip>

30 Use **cloud tasks** for work that should run reliably without your machine. Use **Desktop tasks** when you need access to local files and tools. Use **`/loop`** for quick polling during a session.

31</Tip>

32 

33<Note>

34 By default, scheduled tasks run against whatever state your working directory is in, including uncommitted changes. Enable the worktree toggle when creating the task to give each run its own isolated Git worktree, the same way [parallel sessions](/en/desktop#work-in-parallel-with-sessions) work.

35</Note>

36 

37## Create a scheduled task

38 

39Click **Routines** in the sidebar, then click **New routine** and choose **Local**. Configure these fields:

40 

41| Field | Description |

42| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

43| Name | Identifier for the task. Converted to lowercase kebab-case and used as the folder name on disk. Must be unique across your tasks. |

44| Description | Short summary shown in the task list. |

45| Instructions | What Claude should do when the task runs. Write this the same way you'd write any message in the prompt box. The instructions input includes pickers for the permission mode and model, and below it you select the working folder and whether to run in an isolated worktree. |

46| Schedule | How often the task runs. See [schedule options](#schedule-options) below. |

47 

48A folder is required before you can save the task. If you haven't trusted that folder yet, Desktop prompts you to trust it before saving.

49 

50You can also create a task by describing what you want in any session. For example, "set up a daily code review that runs every morning at 9am" creates a recurring task, and "remind me at 3pm tomorrow to check the deploy" creates a one-time task that disables itself after it fires.

51 

52## Schedule options

53 

54Pick a preset from the Schedule control:

55 

56* **Manual**: no schedule, only runs when you click **Run now**. Useful for saving a prompt you trigger on demand

57* **Hourly**: runs every hour

58* **Daily**: shows a time picker, defaults to 9:00 AM local time

59* **Weekdays**: same as Daily but skips Saturday and Sunday

60* **Weekly**: shows a time picker and a day picker

61 

62For intervals the picker doesn't offer, such as every 15 minutes, the first of each month, or a single run at a specific future time, ask Claude in any Desktop session to set the schedule. Use plain language; for example, "schedule a task to run all the tests every 6 hours."

63 

64## How scheduled tasks run

65 

66Scheduled tasks run on your machine. Desktop checks the schedule every minute while the app is open and starts a fresh session when a task is due, independent of any manual sessions you have open. Each task gets a small delay of a few minutes after the scheduled time to stagger API traffic. The delay is deterministic: the same task always starts at the same offset.

67 

68When a task fires, you get a desktop notification and a new session appears under a **Scheduled** section in the sidebar. Open it to see what Claude did, review changes, or respond to permission prompts. The session works like any other: Claude can edit files, run commands, create commits, and open pull requests.

69 

70Tasks only run while the desktop app is running and your computer is awake. If your computer sleeps through a scheduled time, the run is skipped. To prevent idle-sleep, enable **Keep computer awake** in Settings under **Desktop app → General**. Closing the laptop lid still puts it to sleep. For tasks that need to run even when your computer is off, or that should trigger on an API call or GitHub event, create a remote [routine](/en/routines) instead.

71 

72## Missed runs

73 

74When the app starts or your computer wakes, Desktop checks whether each task missed any runs in the last seven days. If it did, Desktop starts exactly one catch-up run for the most recently missed time and discards anything older. A daily task that missed six days runs once on wake. Desktop shows a notification when a catch-up run starts.

75 

76Keep this in mind when writing prompts. A task scheduled for 9am might run at 11pm if your computer was asleep all day. If timing matters, add guardrails to the prompt itself, for example: "Only review today's commits. If it's after 5pm, skip the review and just post a summary of what was missed."

77 

78## Permissions for scheduled tasks

79 

80Each task has its own permission mode, which you set when creating or editing the task. Allow rules from `~/.claude/settings.json` also apply to scheduled task sessions. If a task runs in Ask mode and needs to run a tool it doesn't have permission for, the run stalls until you approve it. The session stays open in the sidebar so you can answer later.

81 

82To avoid stalls, click **Run now** after creating a task, watch for permission prompts, and select "always allow" for each one. Future runs of that task auto-approve the same tools without prompting. You can review and revoke these approvals from the task's detail page.

83 

84## Manage scheduled tasks

85 

86Click a task in the **Routines** list to open its detail page. From here you can:

87 

88* **Run now**: start the task immediately without waiting for the next scheduled time

89* **Status**: toggle between Active and Paused to pause or resume scheduled runs without deleting the task

90* **Edit**: change the instructions, schedule, folder, or other settings

91* **Review history**: see every past run, including skipped runs. Hover a skipped entry to see why: your computer was asleep, the previous run was still in progress, or other scheduled tasks were already running. Click **Show more** to load older entries.

92* **Review allowed permissions**: see and revoke saved tool approvals for this task from the **Always allowed** panel

93* **Delete**: remove the task and archive all sessions it created

94 

95You can also list, create, edit, and pause tasks by asking Claude in any Desktop session. For example, "pause my dependency-audit task" or "show me my scheduled tasks." To delete a task, use the **Delete** button on its detail page.

96 

97To edit a task's prompt on disk, open `~/.claude/scheduled-tasks/<task-name>/SKILL.md` (or under [`CLAUDE_CONFIG_DIR`](/en/env-vars) if set). The file uses YAML frontmatter for `name` and `description`, with the prompt as the body. Changes take effect on the next run. Schedule, folder, model, and enabled state are not in this file: change them through the Edit form or ask Claude.

98 

99## Related resources

100 

101* [Routines](/en/routines): run tasks on Anthropic-managed infrastructure on a schedule, via API call, or in response to GitHub events, even when your computer is off

102* [Run prompts on a schedule](/en/scheduled-tasks): session-scoped scheduling with `/loop` in the CLI

103* [Claude Code GitHub Actions](/en/github-actions): run Claude on a schedule in CI instead of on your machine

104* [Use Claude Code Desktop](/en/desktop): the full Desktop app guide

devcontainer.md +161 −48

Details

4 4 

5# Development containers5# Development containers

6 6 

7> Learn about the Claude Code development container for teams that need consistent, secure environments.7> Run Claude Code inside a dev container for consistent, isolated environments across your team.

8 8 

9The reference [devcontainer setup](https://github.com/anthropics/claude-code/tree/main/.devcontainer) and associated [Dockerfile](https://github.com/anthropics/claude-code/blob/main/.devcontainer/Dockerfile) offer a preconfigured development container that you can use as is, or customize for your needs. This devcontainer works with the Visual Studio Code [Dev Containers extension](https://code.visualstudio.com/docs/devcontainers/containers) and similar tools.9A [development container](https://containers.dev/), or dev container, lets you define an identical, isolated environment that every engineer on your team can run. With Claude Code installed in that container, commands Claude runs execute inside it rather than on the host machine, while edits to your project files appear in your local repository as you work.

10 10 

11The container's enhanced security measures (isolation and firewall rules) allow you to run `claude --dangerously-skip-permissions` to bypass permission prompts for unattended operation.11This page covers [installing Claude Code in a dev container](#add-claude-code-to-your-dev-container) and the configuration topics that follow. Each topic is self-contained, so jump to the ones that match what you need to set up:

12 

13* [Persist authentication and settings across rebuilds](#persist-authentication-and-settings-across-rebuilds)

14* [Enforce organization policy](#enforce-organization-policy)

15* [Restrict network egress](#restrict-network-egress)

16* [Run without permission prompts](#run-without-permission-prompts)

12 17 

13<Warning>18<Warning>

14 While the devcontainer provides substantial protections, no system is completely immune to all attacks.19 While the dev container provides substantial protections, no system is completely immune to all attacks.

15 When executed with `--dangerously-skip-permissions`, devcontainers don't prevent a malicious project from exfiltrating anything accessible in the devcontainer including Claude Code credentials.20 When executed with `--dangerously-skip-permissions`, dev containers do not prevent a malicious project from exfiltrating anything accessible inside the container, including the Claude Code credentials stored in [`~/.claude`](/en/claude-directory).

16 We recommend only using devcontainers when developing with trusted repositories.21 Only use dev containers when developing with trusted repositories, and monitor Claude's activities.

17 Always maintain good security practices and monitor Claude's activities.22 Avoid mounting host secrets such as `~/.ssh` or cloud credential files into the container; prefer repository-scoped or short-lived tokens.

18</Warning>23</Warning>

19 24 

20## Key features25<Accordion title="How dev containers work with your editor">

26 <img src="https://mintcdn.com/claude-code/YvJyjZfd9yMihr0i/images/devcontainer-architecture.svg?fit=max&auto=format&n=YvJyjZfd9yMihr0i&q=85&s=9017b1d16a446c6cc37ba562f35b9aae" className="dark:hidden" alt="Diagram showing an editor on the host connecting to a Docker dev container. Claude Code, the terminal, and build tools run inside the container. The host repository is bind-mounted into the container as the workspace." width="640" height="300" data-path="images/devcontainer-architecture.svg" />

27 

28 <img src="https://mintcdn.com/claude-code/YvJyjZfd9yMihr0i/images/devcontainer-architecture-dark.svg?fit=max&auto=format&n=YvJyjZfd9yMihr0i&q=85&s=ef00c8e25b1ea7a3a152895f1488831b" className="hidden dark:block" alt="Diagram showing an editor on the host connecting to a Docker dev container. Claude Code, the terminal, and build tools run inside the container. The host repository is bind-mounted into the container as the workspace." width="640" height="300" data-path="images/devcontainer-architecture-dark.svg" />

29 

30 A dev container runs as a Docker container, either on your machine or on a cloud host such as GitHub Codespaces. An editor that supports the Dev Containers spec, such as VS Code, GitHub Codespaces, a JetBrains IDE, or Cursor, connects to that container: you browse and edit files in the editor as usual, but the integrated terminal, language servers, and build tools all run inside the container rather than on your host. Editors without dev container support, such as plain Vim, are not part of this workflow.

31 

32 Claude Code runs inside the container, so it sees the same files, dependencies, and tools as the rest of your project's toolchain. In VS Code you can use either the [Claude Code extension panel](/en/vs-code) or run `claude` in the integrated terminal; both run inside the container and share the same `~/.claude` configuration.

33</Accordion>

34 

35## Add Claude Code to your dev container

36 

37Claude Code installs into any dev container through the [Claude Code Dev Container Feature](https://github.com/anthropics/devcontainer-features/tree/main/src/claude-code).

38 

39The settings work with any tool that supports the Dev Containers spec, such as VS Code, GitHub Codespaces, or JetBrains IDEs. The steps below use VS Code as an example.

40 

41When you open the container in VS Code or Codespaces, the feature also adds the Claude Code VS Code extension; other editors ignore that part.

42 

43<Tip>

44 New to dev containers? The [VS Code Dev Containers tutorial](https://code.visualstudio.com/docs/devcontainers/tutorial) walks through installing Docker, the extension, and opening your first container. For a fuller hardened example with a firewall and persistent volumes, see [Try the reference container](#try-the-reference-container).

45</Tip>

46 

47<Steps>

48 <Step title="Create or update devcontainer.json">

49 Save the following as `.devcontainer/devcontainer.json` in your repository, or add the `features` block to your existing file.

50 

51 The version tag at the end, such as `:1.0`, pins the feature's install script, not the Claude Code release. The feature installs the latest Claude Code, and Claude Code auto-updates itself inside the container by default.

52 

53 To pin the CLI version or disable auto-update, see [Enforce organization policy](#enforce-organization-policy).

54 

55 ```json .devcontainer/devcontainer.json theme={null}

56 {

57 "image": "mcr.microsoft.com/devcontainers/base:ubuntu",

58 "features": {

59 "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}

60 }

61 }

62 ```

63 

64 Replace the `image` line with your project's base image or remove it if your existing file uses a Dockerfile.

65 </Step>

66 

67 <Step title="Rebuild the container">

68 Open the VS Code Command Palette with `Cmd+Shift+P` on Mac or `Ctrl+Shift+P` on Windows and Linux, and run **Dev Containers: Rebuild Container**.

69 

70 For other tools, follow that tool's rebuild action: see [rebuilding in GitHub Codespaces](https://docs.github.com/en/codespaces/developing-in-a-codespace/rebuilding-the-container-in-a-codespace), the [Dev Containers CLI](https://github.com/devcontainers/cli), or your IDE's dev container documentation.

71 </Step>

72 

73 <Step title="Sign in to Claude Code">

74 Open a terminal in the rebuilt container and run `claude`, then follow the authentication prompt.

75 </Step>

76</Steps>

77 

78What you see at the authentication prompt depends on your provider:

79 

80* **Anthropic**: sign in through a browser with your Claude or Anthropic Console account

81* **[Amazon Bedrock, Google Vertex AI, or Microsoft Foundry](/en/third-party-integrations)**: Claude Code uses your cloud provider credentials, with no browser prompt

82 

83For cloud providers, pass credentials into the container as environment variables through `containerEnv`, a Codespaces secret, or your cloud's workload identity rather than mounting credential files from the host. See [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), or [Microsoft Foundry](/en/microsoft-foundry) for the credential chain Claude Code reads.

84 

85See [Choose your API provider](/en/admin-setup#choose-your-api-provider) to decide which path fits your organization.

86 

87<Note>

88 If the browser sign-in completes but the callback never reaches the container, copy the code shown in the browser and paste it at the `Paste code here if prompted` prompt in the terminal. This can happen when the editor's port forwarding doesn't route the localhost callback.

89</Note>

90 

91## Persist authentication and settings across rebuilds

92 

93By default, the container's home directory is discarded on rebuild, so engineers must sign in again each time. Claude Code stores its authentication token, user settings, and session history under [`~/.claude`](/en/claude-directory). Mount a named volume at that path to keep this state across rebuilds.

94 

95The following example mounts a volume at the home directory of the `node` user:

96 

97```json devcontainer.json theme={null}

98"mounts": [

99 "source=claude-code-config,target=/home/node/.claude,type=volume"

100]

101```

102 

103Replace `/home/node` with the home directory of your container's `remoteUser`. If you mount the volume somewhere other than `~/.claude`, set [`CLAUDE_CONFIG_DIR`](/en/env-vars) to the mount path so Claude Code reads and writes there.

104 

105To isolate state per project rather than sharing one volume across all repositories, include the `${devcontainerId}` variable in the source name. The [reference configuration](https://github.com/anthropics/claude-code/blob/main/.devcontainer/devcontainer.json) uses `source=claude-code-config-${devcontainerId}` for this purpose.

106 

107In GitHub Codespaces, `~/.claude` persists across stopping and starting a codespace, but is still cleared when you rebuild the container, so the volume mount above applies there too. To carry authentication across codespaces, store `ANTHROPIC_API_KEY` or a `CLAUDE_CODE_OAUTH_TOKEN` from [`claude setup-token`](/en/authentication#generate-a-long-lived-token) as a [Codespaces secret](https://docs.github.com/en/codespaces/managing-your-codespaces/managing-your-account-specific-secrets-for-github-codespaces); Codespaces makes secrets available as environment variables inside the container automatically.

108 

109## Enforce organization policy

110 

111A dev container is a convenient place to apply organization policy, because the same image and configuration run on every engineer's machine.

112 

113Claude Code reads `/etc/claude-code/managed-settings.json` on Linux and applies it at the highest precedence in the [settings hierarchy](/en/settings#how-scopes-interact), so values there override anything an engineer sets in `~/.claude` or the project's `.claude/` directory. Copy the file into place from your Dockerfile:

114 

115```dockerfile Dockerfile theme={null}

116RUN mkdir -p /etc/claude-code

117COPY managed-settings.json /etc/claude-code/managed-settings.json

118```

119 

120Because the Dockerfile lives in the repository, anyone with write access can change or remove this step. For policy that engineers cannot bypass by editing repository files, deliver managed settings through [server-managed settings](/en/server-managed-settings) or your MDM instead. See [managed settings files](/en/settings#settings-files) for the available keys and the other delivery paths.

121 

122To set [environment variables](/en/env-vars) that apply to every Claude Code session in the container, add them to `containerEnv` in your `devcontainer.json`. The following example opts out of telemetry and error reporting and prevents Claude Code from auto-updating after install:

123 

124```json devcontainer.json theme={null}

125"containerEnv": {

126 "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",

127 "DISABLE_AUTOUPDATER": "1"

128}

129```

130 

131The Dev Container Feature always installs the latest Claude Code release. To pin a specific Claude Code version for reproducible builds, install it from your Dockerfile with `npm install -g @anthropic-ai/claude-code@X.Y.Z` instead of using the feature, and set `DISABLE_AUTOUPDATER` as shown above.

21 132 

22* **Production-ready Node.js**: Built on Node.js 20 with essential development dependencies133For the full list of policy controls including permission rules, tool restrictions, and MCP server allowlists, see [Set up Claude Code for your organization](/en/admin-setup).

23* **Security by design**: Custom firewall restricting network access to only necessary services

24* **Developer-friendly tools**: Includes git, ZSH with productivity enhancements, fzf, and more

25* **Seamless VS Code integration**: Pre-configured extensions and optimized settings

26* **Session persistence**: Preserves command history and configurations between container restarts

27* **Works everywhere**: Compatible with macOS, Windows, and Linux development environments

28 134 

29## Getting started in 4 steps135To make [MCP servers](/en/mcp) available inside the container, define them at [project scope](/en/mcp#mcp-installation-scopes) in a `.mcp.json` file at the repository root so they are checked in alongside your dev container configuration. Install any binaries that local stdio servers depend on in your Dockerfile, and add remote server domains to your network allowlist.

30 136 

311. Install VS Code and the Remote - Containers extension137## Restrict network egress

322. Clone the [Claude Code reference implementation](https://github.com/anthropics/claude-code/tree/main/.devcontainer) repository

333. Open the repository in VS Code

344. When prompted, click "Reopen in Container" (or use Command Palette: Cmd+Shift+P → "Remote-Containers: Reopen in Container")

35 138 

36## Configuration breakdown139You can limit the container's outbound traffic to only the domains Claude Code needs. See [Network access requirements](/en/network-config#network-access-requirements) for the inference and authentication domains, and [Telemetry services](/en/data-usage#telemetry-services) for the optional telemetry and error reporting connections and how to disable them.

37 140 

38The devcontainer setup consists of three primary components:141The reference container includes an [`init-firewall.sh`](https://github.com/anthropics/claude-code/blob/main/.devcontainer/init-firewall.sh) script that blocks all outbound traffic except the domains Claude Code and your development tools need. Running a firewall inside a container requires extra permissions, so the reference adds the `NET_ADMIN` and `NET_RAW` capabilities through `runArgs`. The firewall script and these capabilities are not required for Claude Code itself: you can leave them out and rely on your own network controls instead.

39 142 

40* [**devcontainer.json**](https://github.com/anthropics/claude-code/blob/main/.devcontainer/devcontainer.json): Controls container settings, extensions, and volume mounts143## Run without permission prompts

41* [**Dockerfile**](https://github.com/anthropics/claude-code/blob/main/.devcontainer/Dockerfile): Defines the container image and installed tools

42* [**init-firewall.sh**](https://github.com/anthropics/claude-code/blob/main/.devcontainer/init-firewall.sh): Establishes network security rules

43 144 

44## Security features145Because the container runs Claude Code as a non-root user and confines command execution to the container, you can pass `--dangerously-skip-permissions` for unattended operation. The CLI rejects this flag when launched as root, so confirm `remoteUser` is set to a non-root account.

45 146 

46The container implements a multi-layered security approach with its firewall configuration:147Skipping permission prompts removes your opportunity to review tool calls before they run. Claude can still modify any file in the bind-mounted workspace, which appears directly on your host, and reach anything the container's network policy allows. Pair this flag with the [network egress restrictions](#restrict-network-egress) above to limit what a bypassed session can reach.

47 148 

48* **Precise access control**: Restricts outbound connections to whitelisted domains only (npm registry, GitHub, Claude API, etc.)149If you want fewer prompts without disabling safety checks, consider [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) instead, which has a classifier review actions before they run. To prevent engineers from using `--dangerously-skip-permissions` at all, set `permissions.disableBypassPermissionsMode` to `"disable"` in [managed settings](/en/settings#permission-settings).

49* **Allowed outbound connections**: The firewall permits outbound DNS and SSH connections

50* **Default-deny policy**: Blocks all other external network access

51* **Startup verification**: Validates firewall rules when the container initializes

52* **Isolation**: Creates a secure development environment separated from your main system

53 150 

54## Customization options151## Try the reference container

55 152 

56The devcontainer configuration is designed to be adaptable to your needs:153The [`anthropics/claude-code`](https://github.com/anthropics/claude-code/tree/main/.devcontainer) repository includes an example dev container that combines the CLI, the egress firewall, persistent volumes, and a Zsh-based shell. It is provided as a working example rather than a maintained base image; use it to see how the pieces fit together before applying them to your own configuration.

57 154 

58* Add or remove VS Code extensions based on your workflow155<Steps>

59* Modify resource allocations for different hardware environments156 <Step title="Install prerequisites">

60* Adjust network access permissions157 Install VS Code and the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers).

61* Customize shell configurations and developer tooling158 </Step>

62 159 

63## Example use cases160 <Step title="Clone the reference">

161 Clone the [Claude Code repository](https://github.com/anthropics/claude-code) and open it in VS Code.

162 </Step>

64 163 

65### Secure client work164 <Step title="Reopen in container">

165 When prompted, click **Reopen in Container**, or run **Dev Containers: Reopen in Container** from the Command Palette.

166 </Step>

66 167 

67Use devcontainers to isolate different client projects, ensuring code and credentials never mix between environments.168 <Step title="Start Claude Code">

169 Once the container finishes building, open a terminal with `` Ctrl+` `` and run `claude` to sign in and start your first session.

170 </Step>

171</Steps>

68 172 

69### Team onboarding173To use this configuration with your own project, copy the `.devcontainer/` directory into your repository and adjust the Dockerfile for your toolchain, or return to [Add Claude Code to your dev container](#add-claude-code-to-your-dev-container) to add only the feature to a setup you already have.

70 174 

71New team members can get a fully configured development environment in minutes, with all necessary tools and settings pre-installed.175The reference configuration consists of three files. None of them are required when you add Claude Code to your own dev container through the feature, but they show one way to combine the pieces.

72 176 

73### Consistent CI/CD environments177| File | Purpose |

178| ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |

179| [`devcontainer.json`](https://github.com/anthropics/claude-code/blob/main/.devcontainer/devcontainer.json) | Volume mounts, `runArgs` capabilities, VS Code extensions, and `containerEnv` |

180| [`Dockerfile`](https://github.com/anthropics/claude-code/blob/main/.devcontainer/Dockerfile) | Base image, development tools, and the Claude Code install |

181| [`init-firewall.sh`](https://github.com/anthropics/claude-code/blob/main/.devcontainer/init-firewall.sh) | Blocks all outbound network traffic except the allowed domains |

74 182 

75Mirror your devcontainer configuration in CI/CD pipelines to ensure development and production environments match.183## Next steps

76 184 

77## Related resources185Once Claude Code is running in your dev container, the pages below cover the rest of an organization rollout: choosing an authentication path, delivering managed policy outside the repository, monitoring usage, and understanding what Claude Code stores and sends.

78 186 

79* [VS Code devcontainers documentation](https://code.visualstudio.com/docs/devcontainers/containers)187* [Set up Claude Code for your organization](/en/admin-setup): choose an authentication provider, decide how policy reaches devices, and plan the rollout

80* [Claude Code security best practices](/en/security)188* [Server-managed settings](/en/server-managed-settings): deliver managed policy from the Claude.ai admin console so engineers cannot bypass it by editing repository files

81* [Enterprise network configuration](/en/network-config)189* [Monitor usage and audit activity](/en/monitoring-usage): export OpenTelemetry metrics and review what your team is running

190* [Network access requirements](/en/network-config#network-access-requirements): the full domain allowlist for proxies and firewalls

191* [Telemetry services and opt-out](/en/data-usage#telemetry-services): what Claude Code sends by default and the environment variables that disable it

192* [Explore the `.claude` directory](/en/claude-directory): what the volume mount holds, including credentials, settings, and session history

193* [Security model](/en/security): how Claude Code's permission system, sandboxing, and prompt-injection protections fit together

194* [Permission modes](/en/permission-modes): the full range from plan mode to auto mode to bypass, and when to use each

Details

4 4 

5# Discover and install prebuilt plugins through marketplaces5# Discover and install prebuilt plugins through marketplaces

6 6 

7> Find and install plugins from marketplaces to extend Claude Code with new commands, agents, and capabilities.7> Find and install plugins from marketplaces to extend Claude Code with new skills, agents, and capabilities.

8 8 

9Plugins extend Claude Code with skills, agents, hooks, and MCP servers. Plugin marketplaces are catalogs that help you discover and install these extensions without building them yourself.9Plugins extend Claude Code with skills, agents, hooks, and MCP servers. Plugin marketplaces are catalogs that help you discover and install these extensions without building them yourself.

10 10 


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 

39If Claude Code reports that the plugin is not found in any marketplace, your marketplace is either missing or outdated. Run `/plugin marketplace update claude-plugins-official` to refresh it, or `/plugin marketplace add anthropics/claude-plugins-official` if you haven't added it before. Then retry the install.

40 

39<Note>41<Note>

40 The official marketplace is maintained by Anthropic. To distribute your own plugins, [create your own marketplace](/en/plugin-marketplaces) and share it with users.42 The official marketplace is maintained by Anthropic. To submit a plugin to the official marketplace, use one of the in-app submission forms:

43 

44 * **Claude.ai**: [claude.ai/settings/plugins/submit](https://claude.ai/settings/plugins/submit)

45 * **Console**: [platform.claude.com/plugins/submit](https://platform.claude.com/plugins/submit)

46 

47 To distribute plugins independently, [create your own marketplace](/en/plugin-marketplaces) and share it with users.

41</Note>48</Note>

42 49 

43The official marketplace includes several categories of plugins:50The official marketplace includes several categories of plugins:


90 97 

91### Development workflows98### Development workflows

92 99 

93Plugins that add commands and agents for common development tasks:100Plugins that add skills and agents for common development tasks:

94 101 

95* **commit-commands**: Git commit workflows including commit, push, and PR creation102* **commit-commands**: Git commit workflows including commit, push, and PR creation

96* **pr-review-toolkit**: Specialized agents for reviewing pull requests103* **pr-review-toolkit**: Specialized agents for reviewing pull requests


137 * **Project scope**: install for all collaborators on this repository144 * **Project scope**: install for all collaborators on this repository

138 * **Local scope**: install for yourself in this repository only145 * **Local scope**: install for yourself in this repository only

139 146 

140 For example, select **commit-commands** (a plugin that adds git workflow commands) and install it to your user scope.147 For example, select **commit-commands** (a plugin that adds git workflow skills) and install it to your user scope.

141 148 

142 You can also install directly from the command line:149 You can also install directly from the command line:

143 150 


149 </Step>156 </Step>

150 157 

151 <Step title="Use your new plugin">158 <Step title="Use your new plugin">

152 After installing, the plugin's commands are immediately available. Plugin commands are namespaced by the plugin name, so **commit-commands** provides commands like `/commit-commands:commit`.159 After installing, run `/reload-plugins` to activate the plugin. Plugin skills are namespaced by the plugin name, so **commit-commands** provides skills like `/commit-commands:commit`.

153 160 

154 Try it out by making a change to a file and running:161 Try it out by making a change to a file and running:

155 162 


159 166 

160 This stages your changes, generates a commit message, and creates the commit.167 This stages your changes, generates a commit message, and creates the commit.

161 168 

162 Each plugin works differently. Check the plugin's description in the **Discover** tab or its homepage to learn what commands and capabilities it provides.169 Each plugin works differently. Check the plugin's description in the **Discover** tab or its homepage to learn what skills and capabilities it provides.

163 </Step>170 </Step>

164</Steps>171</Steps>

165 172 


252 259 

253You may also see plugins with **managed** scope—these are installed by administrators via [managed settings](/en/settings#settings-files) and cannot be modified.260You may also see plugins with **managed** scope—these are installed by administrators via [managed settings](/en/settings#settings-files) and cannot be modified.

254 261 

255Run `/plugin` and go to the **Installed** tab to see your plugins grouped by scope.

256 

257<Warning>262<Warning>

258 Make sure you trust a plugin before installing it. Anthropic does not control what MCP servers, files, or other software are included in plugins and cannot verify that they work as intended. Check each plugin's homepage for more information.263 Make sure you trust a plugin before installing it. Anthropic does not control what MCP servers, files, or other software are included in plugins and cannot verify that they work as intended. Check each plugin's homepage for more information.

259</Warning>264</Warning>

260 265 

261## Manage installed plugins266## Manage installed plugins

262 267 

263Run `/plugin` and go to the **Installed** tab to view, enable, disable, or uninstall your plugins. Type to filter the list by plugin name or description.268Run `/plugin` and go to the **Installed** tab to view, enable, disable, or uninstall your plugins. The list is grouped by scope and sorted so you see problems first: plugins with load errors or unresolved dependencies appear at the top, followed by your favorites, with disabled plugins folded behind a collapsed header at the bottom.

269 

270From the list you can:

271 

272* press `f` to favorite or unfavorite the selected plugin

273* type to filter by plugin name or description

274* press Enter to open a plugin's detail view and enable, disable, or uninstall it

275 

276When you install a plugin that declares dependencies, the install output lists which dependencies were auto-installed alongside it.

264 277 

265You can also manage plugins with direct commands.278You can also manage plugins with direct commands.

266 279 


289claude plugin uninstall formatter@your-org --scope project302claude plugin uninstall formatter@your-org --scope project

290```303```

291 304 

305### Apply plugin changes without restarting

306 

307When you install, enable, or disable plugins during a session, run `/reload-plugins` to pick up all changes without restarting:

308 

309```shell theme={null}

310/reload-plugins

311```

312 

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

314 

292## Manage marketplaces315## Manage marketplaces

293 316 

294You can manage marketplaces through the interactive `/plugin` interface or with CLI commands.317You can manage marketplaces through the interactive `/plugin` interface or with CLI commands.


330 353 

331### Configure auto-updates354### Configure auto-updates

332 355 

333Claude Code can automatically update marketplaces and their installed plugins at startup. When auto-update is enabled for a marketplace, Claude Code refreshes the marketplace data and updates installed plugins to their latest versions. If any plugins were updated, you'll see a notification suggesting you restart Claude Code.356Claude Code can automatically update marketplaces and their installed plugins at startup. When auto-update is enabled for a marketplace, Claude Code refreshes the marketplace data and updates installed plugins to their latest versions. If any plugins were updated, you'll see a notification prompting you to run `/reload-plugins`.

334 357 

335Toggle auto-update for individual marketplaces through the UI:358Toggle auto-update for individual marketplaces through the UI:

336 359 


343 366 

344To disable all automatic updates entirely for both Claude Code and all plugins, set the `DISABLE_AUTOUPDATER` environment variable. See [Auto updates](/en/setup#auto-updates) for details.367To disable all automatic updates entirely for both Claude Code and all plugins, set the `DISABLE_AUTOUPDATER` environment variable. See [Auto updates](/en/setup#auto-updates) for details.

345 368 

346To keep plugin auto-updates enabled while disabling Claude Code auto-updates, set `FORCE_AUTOUPDATE_PLUGINS=true` along with `DISABLE_AUTOUPDATER`:369To keep plugin auto-updates enabled while disabling Claude Code auto-updates, set `FORCE_AUTOUPDATE_PLUGINS=1` along with `DISABLE_AUTOUPDATER`:

347 370 

348```shell theme={null}371```bash theme={null}

349export DISABLE_AUTOUPDATER=true372export DISABLE_AUTOUPDATER=1

350export FORCE_AUTOUPDATE_PLUGINS=true373export FORCE_AUTOUPDATE_PLUGINS=1

351```374```

352 375 

353This is useful when you want to manage Claude Code updates manually but still receive automatic plugin updates.376This is useful when you want to manage Claude Code updates manually but still receive automatic plugin updates.


356 379 

357Team admins can set up automatic marketplace installation for projects by adding marketplace configuration to `.claude/settings.json`. When team members trust the repository folder, Claude Code prompts them to install these marketplaces and plugins.380Team admins can set up automatic marketplace installation for projects by adding marketplace configuration to `.claude/settings.json`. When team members trust the repository folder, Claude Code prompts them to install these marketplaces and plugins.

358 381 

382Add `extraKnownMarketplaces` to your project's `.claude/settings.json`:

383 

384```json theme={null}

385{

386 "extraKnownMarketplaces": {

387 "my-team-tools": {

388 "source": {

389 "source": "github",

390 "repo": "your-org/claude-plugins"

391 }

392 }

393 }

394}

395```

396 

359For full configuration options including `extraKnownMarketplaces` and `enabledPlugins`, see [Plugin settings](/en/settings#plugin-settings).397For full configuration options including `extraKnownMarketplaces` and `enabledPlugins`, see [Plugin settings](/en/settings#plugin-settings).

360 398 

399## Security

400 

401Plugins and marketplaces are highly trusted components that can execute arbitrary code on your machine with your user privileges. Only install plugins and add marketplaces from sources you trust. Organizations can restrict which marketplaces users are allowed to add using [managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions).

402 

361## Troubleshooting403## Troubleshooting

362 404 

363### /plugin command not recognized405### /plugin command not recognized

364 406 

365If you see "unknown command" or the `/plugin` command doesn't appear:407If you see "unknown command" or the `/plugin` command doesn't appear:

366 408 

3671. **Check your version**: Run `claude --version`. Plugins require version 1.0.33 or later.4091. **Check your version**: Run `claude --version` to see what's installed.

3682. **Update Claude Code**:4102. **Update Claude Code**:

369 * **Homebrew**: `brew upgrade claude-code`411 * **Homebrew**: `brew upgrade claude-code` (or `brew upgrade claude-code@latest` if you installed that cask)

370 * **npm**: `npm update -g @anthropic-ai/claude-code`412 * **npm**: `npm update -g @anthropic-ai/claude-code`

371 * **Native installer**: Re-run the install command from [Setup](/en/setup)413 * **Native installer**: Re-run the install command from [Setup](/en/setup)

3723. **Restart Claude Code**: After updating, restart your terminal and run `claude` again.4143. **Restart Claude Code**: After updating, restart your terminal and run `claude` again.

env-vars.md +230 −0 added

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# Environment variables

6 

7> Complete reference for environment variables that control Claude Code behavior.

8 

9Claude Code supports the following environment variables to control its behavior. Set them in your shell before launching `claude`, or configure them in [`settings.json`](/en/settings#available-settings) under the `env` key to apply them to every session or roll them out across your team.

10 

11| Variable | Purpose |

12| :------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

13| `ANTHROPIC_API_KEY` | API key sent as `X-Api-Key` header. When set, this key is used instead of your Claude Pro, Max, Team, or Enterprise subscription even if you are logged in. In non-interactive mode (`-p`), the key is always used when present. In interactive mode, you are prompted to approve the key once before it overrides your subscription. To use your subscription instead, run `unset ANTHROPIC_API_KEY` |

14| `ANTHROPIC_AUTH_TOKEN` | Custom value for the `Authorization` header (the value you set here will be prefixed with `Bearer `) |

15| `ANTHROPIC_BASE_URL` | Override the API endpoint to route requests through a proxy or gateway. When set to a non-first-party host, [MCP tool search](/en/mcp#scale-with-mcp-tool-search) is disabled by default. Set `ENABLE_TOOL_SEARCH=true` if your proxy forwards `tool_reference` blocks |

16| `ANTHROPIC_BEDROCK_BASE_URL` | Override the Bedrock endpoint URL. Use for custom Bedrock endpoints or when routing through an [LLM gateway](/en/llm-gateway). See [Amazon Bedrock](/en/amazon-bedrock) |

17| `ANTHROPIC_BEDROCK_MANTLE_BASE_URL` | Override the Bedrock Mantle endpoint URL. See [Mantle endpoint](/en/amazon-bedrock#use-the-mantle-endpoint) |

18| `ANTHROPIC_BETAS` | Comma-separated list of additional `anthropic-beta` header values to include in API requests. Claude Code already sends the beta headers it needs; use this to opt into an [Anthropic API beta](https://platform.claude.com/docs/en/api/beta-headers) before Claude Code adds native support. Unlike the [`--betas` flag](/en/cli-reference#cli-flags), which requires API key authentication, this variable works with all auth methods including Claude.ai subscription |

19| `ANTHROPIC_CUSTOM_HEADERS` | Custom headers to add to requests (`Name: Value` format, newline-separated for multiple headers) |

20| `ANTHROPIC_CUSTOM_MODEL_OPTION` | Model ID to add as a custom entry in the `/model` picker. Use this to make a non-standard or gateway-specific model selectable without replacing built-in aliases. See [Model configuration](/en/model-config#add-a-custom-model-option) |

21| `ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION` | Display description for the custom model entry in the `/model` picker. Defaults to `Custom model (<model-id>)` when not set |

22| `ANTHROPIC_CUSTOM_MODEL_OPTION_NAME` | Display name for the custom model entry in the `/model` picker. Defaults to the model ID when not set |

23| `ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

24| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | See [Model configuration](/en/model-config#environment-variables) |

25| `ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

26| `ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

27| `ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

28| `ANTHROPIC_DEFAULT_OPUS_MODEL` | See [Model configuration](/en/model-config#environment-variables) |

29| `ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

30| `ANTHROPIC_DEFAULT_OPUS_MODEL_NAME` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

31| `ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

32| `ANTHROPIC_DEFAULT_SONNET_MODEL` | See [Model configuration](/en/model-config#environment-variables) |

33| `ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

34| `ANTHROPIC_DEFAULT_SONNET_MODEL_NAME` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

35| `ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES` | See [Model configuration](/en/model-config#customize-pinned-model-display-and-capabilities) |

36| `ANTHROPIC_FOUNDRY_API_KEY` | API key for Microsoft Foundry authentication (see [Microsoft Foundry](/en/microsoft-foundry)) |

37| `ANTHROPIC_FOUNDRY_BASE_URL` | Full base URL for the Foundry resource (for example, `https://my-resource.services.ai.azure.com/anthropic`). Alternative to `ANTHROPIC_FOUNDRY_RESOURCE` (see [Microsoft Foundry](/en/microsoft-foundry)) |

38| `ANTHROPIC_FOUNDRY_RESOURCE` | Foundry resource name (for example, `my-resource`). Required if `ANTHROPIC_FOUNDRY_BASE_URL` is not set (see [Microsoft Foundry](/en/microsoft-foundry)) |

39| `ANTHROPIC_MODEL` | Name of the model setting to use (see [Model Configuration](/en/model-config#environment-variables)) |

40| `ANTHROPIC_SMALL_FAST_MODEL` | \[DEPRECATED] Name of [Haiku-class model for background tasks](/en/costs) |

41| `ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION` | Override AWS region for the Haiku-class model when using Bedrock or Bedrock Mantle |

42| `ANTHROPIC_VERTEX_BASE_URL` | Override the Vertex AI endpoint URL. Use for custom Vertex endpoints or when routing through an [LLM gateway](/en/llm-gateway). See [Google Vertex AI](/en/google-vertex-ai) |

43| `ANTHROPIC_VERTEX_PROJECT_ID` | GCP project ID for Vertex AI. Required when using [Google Vertex AI](/en/google-vertex-ai) |

44| `API_TIMEOUT_MS` | Timeout for API requests in milliseconds (default: 600000, or 10 minutes; maximum: 2147483647). Increase this when requests time out on slow networks or when routing through a proxy. Values above the maximum overflow the underlying timer and cause requests to fail immediately |

45| `AWS_BEARER_TOKEN_BEDROCK` | Bedrock API key for authentication (see [Bedrock API keys](https://aws.amazon.com/blogs/machine-learning/accelerate-ai-development-with-amazon-bedrock-api-keys/)) |

46| `BASH_DEFAULT_TIMEOUT_MS` | Default timeout for long-running bash commands (default: 120000, or 2 minutes) |

47| `BASH_MAX_OUTPUT_LENGTH` | Maximum number of characters in bash outputs before they are middle-truncated |

48| `BASH_MAX_TIMEOUT_MS` | Maximum timeout the model can set for long-running bash commands (default: 600000, or 10 minutes) |

49| `CCR_FORCE_BUNDLE` | Set to `1` to force [`claude --remote`](/en/claude-code-on-the-web#send-local-repositories-without-github) to bundle and upload your local repository even when GitHub access is available |

50| `CLAUDECODE` | Set to `1` in shell environments Claude Code spawns (Bash tool, tmux sessions). Not set in [hooks](/en/hooks) or [status line](/en/statusline) commands. Use to detect when a script is running inside a shell spawned by Claude Code |

51| `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS` | Set to `1` to disable all built-in [subagent](/en/sub-agents) types such as Explore and Plan. Only applies in non-interactive mode (the `-p` flag). Useful for SDK users who want a blank slate |

52| `CLAUDE_AGENT_SDK_MCP_NO_PREFIX` | Set to `1` to skip the `mcp__<server>__` prefix on tool names from SDK-created MCP servers. Tools use their original names. SDK usage only |

53| `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` | Set the percentage of context capacity (1-100) at which auto-compaction triggers. By default, auto-compaction triggers at approximately 95% capacity. Use lower values like `50` to compact earlier. Values above the default threshold have no effect. Applies to both main conversations and subagents. This percentage aligns with the `context_window.used_percentage` field available in [status line](/en/statusline) |

54| `CLAUDE_AUTO_BACKGROUND_TASKS` | Set to `1` to force-enable automatic backgrounding of long-running agent tasks. When enabled, subagents are moved to the background after running for approximately two minutes |

55| `CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR` | Return to the original working directory after each Bash or PowerShell command in the main session |

56| `CLAUDE_CODE_ACCESSIBILITY` | Set to `1` to keep the native terminal cursor visible and disable the inverted-text cursor indicator. Allows screen magnifiers like macOS Zoom to track cursor position |

57| `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` | Set to `1` to load memory files from directories specified with `--add-dir`. Loads `CLAUDE.md`, `.claude/CLAUDE.md`, `.claude/rules/*.md`, and `CLAUDE.local.md`. By default, additional directories do not load memory files |

58| `CLAUDE_CODE_API_KEY_HELPER_TTL_MS` | Interval in milliseconds at which credentials should be refreshed (when using [`apiKeyHelper`](/en/settings#available-settings)) |

59| `CLAUDE_CODE_AUTO_COMPACT_WINDOW` | Set the context capacity in tokens used for auto-compaction calculations. Defaults to the model's context window: 200K for standard models or 1M for [extended context](/en/model-config#extended-context) models. Use a lower value like `500000` on a 1M model to treat the window as 500K for compaction purposes. The value is capped at the model's actual context window. `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` is applied as a percentage of this value. Setting this variable decouples the compaction threshold from the status line's `used_percentage`, which always uses the model's full context window |

60| `CLAUDE_CODE_AUTO_CONNECT_IDE` | Override automatic [IDE connection](/en/vs-code). By default, Claude Code connects automatically when launched inside a supported IDE's integrated terminal. Set to `false` to prevent this. Set to `true` to force a connection attempt when auto-detection fails, such as when tmux obscures the parent terminal |

61| `CLAUDE_CODE_CERT_STORE` | Comma-separated list of CA certificate sources for TLS connections. `bundled` is the Mozilla CA set shipped with Claude Code. `system` is the operating system trust store. Default is `bundled,system`. The native binary distribution is required for system store integration. On the Node.js runtime, only the bundled set is used regardless of this value |

62| `CLAUDE_CODE_CLIENT_CERT` | Path to client certificate file for mTLS authentication |

63| `CLAUDE_CODE_CLIENT_KEY` | Path to client private key file for mTLS authentication |

64| `CLAUDE_CODE_CLIENT_KEY_PASSPHRASE` | Passphrase for encrypted CLAUDE\_CODE\_CLIENT\_KEY (optional) |

65| `CLAUDE_CODE_DEBUG_LOGS_DIR` | Override the debug log file path. Despite the name, this is a file path, not a directory. Requires debug mode to be enabled separately via `--debug` or `/debug`: setting this variable alone does not enable logging. The [`--debug-file`](/en/cli-reference#cli-flags) flag does both at once. Defaults to `~/.claude/debug/<session-id>.txt` |

66| `CLAUDE_CODE_DEBUG_LOG_LEVEL` | Minimum log level written to the debug log file. Values: `verbose`, `debug` (default), `info`, `warn`, `error`. Set to `verbose` to include high-volume diagnostics like full status line command output, or raise to `error` to reduce noise |

67| `CLAUDE_CODE_DISABLE_1M_CONTEXT` | Set to `1` to disable [1M context window](/en/model-config#extended-context) support. When set, 1M model variants are unavailable in the model picker. Useful for enterprise environments with compliance requirements |

68| `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` | Set to `1` to disable [adaptive reasoning](/en/model-config#adjust-effort-level) on Opus 4.6 and Sonnet 4.6 and fall back to the fixed thinking budget controlled by `MAX_THINKING_TOKENS`. {/* min-version: 2.1.111 */}Has no effect on Opus 4.7, which always uses adaptive reasoning |

69| `CLAUDE_CODE_DISABLE_ATTACHMENTS` | Set to `1` to disable attachment processing. File mentions with `@` syntax are sent as plain text instead of being expanded into file content |

70| `CLAUDE_CODE_DISABLE_AUTO_MEMORY` | Set to `1` to disable [auto memory](/en/memory#auto-memory). Set to `0` to force auto memory on during the gradual rollout. When disabled, Claude does not create or load auto memory files |

71| `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` | Set to `1` to disable all background task functionality, including the `run_in_background` parameter on Bash and subagent tools, auto-backgrounding, and the Ctrl+B shortcut |

72| `CLAUDE_CODE_DISABLE_CLAUDE_MDS` | Set to `1` to prevent loading any CLAUDE.md memory files into context, including user, project, and auto-memory files |

73| `CLAUDE_CODE_DISABLE_CRON` | Set to `1` to disable [scheduled tasks](/en/scheduled-tasks). The `/loop` skill and cron tools become unavailable and any already-scheduled tasks stop firing, including tasks that are already running mid-session |

74| `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` | Set to `1` to strip Anthropic-specific `anthropic-beta` request headers and beta tool-schema fields (such as `defer_loading` and `eager_input_streaming`) from API requests. Use this when a proxy gateway rejects requests with errors like "Unexpected value(s) for the `anthropic-beta` header" or "Extra inputs are not permitted". Standard fields (`name`, `description`, `input_schema`, `cache_control`) are preserved. |

75| `CLAUDE_CODE_DISABLE_FAST_MODE` | Set to `1` to disable [fast mode](/en/fast-mode) |

76| `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY` | Set to `1` to disable the "How is Claude doing?" session quality surveys. Surveys are also disabled when `DISABLE_TELEMETRY` or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` is set. See [Session quality surveys](/en/data-usage#session-quality-surveys) |

77| `CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING` | Set to `1` to disable file [checkpointing](/en/checkpointing). The `/rewind` command will not be able to restore code changes |

78| `CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS` | Set to `1` to remove built-in commit and PR workflow instructions and the git status snapshot from Claude's system prompt. Useful when using your own git workflow skills. Takes precedence over the [`includeGitInstructions`](/en/settings#available-settings) setting when set |

79| `CLAUDE_CODE_DISABLE_LEGACY_MODEL_REMAP` | Set to `1` to prevent automatic remapping of Opus 4.0 and 4.1 to the current Opus version on the Anthropic API. Use when you intentionally want to pin an older model. The remap does not run on Bedrock, Vertex, or Foundry |

80| `CLAUDE_CODE_DISABLE_MOUSE` | Set to `1` to disable mouse tracking in [fullscreen rendering](/en/fullscreen). Keyboard scrolling with `PgUp` and `PgDn` still works. Use this to keep your terminal's native copy-on-select behavior |

81| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | Equivalent of setting `DISABLE_AUTOUPDATER`, `DISABLE_FEEDBACK_COMMAND`, `DISABLE_ERROR_REPORTING`, and `DISABLE_TELEMETRY` |

82| `CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK` | Set to `1` to disable the non-streaming fallback when a streaming request fails mid-stream. Streaming errors propagate to the retry layer instead. Useful when a proxy or gateway causes the fallback to produce duplicate tool execution |

83| `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL` | Set to `1` to skip automatic addition of the official plugin marketplace on first run |

84| `CLAUDE_CODE_DISABLE_TERMINAL_TITLE` | Set to `1` to disable automatic terminal title updates based on conversation context |

85| `CLAUDE_CODE_DISABLE_THINKING` | Set to `1` to force-disable [extended thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking) regardless of model support or other settings. More direct than `MAX_THINKING_TOKENS=0` |

86| `CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL` | Set to `1` to disable virtual scrolling in [fullscreen rendering](/en/fullscreen) and render every message in the transcript. Use this if scrolling in fullscreen mode shows blank regions where messages should appear |

87| `CLAUDE_CODE_EFFORT_LEVEL` | Set the effort level for supported models. Values: `low`, `medium`, `high`, `xhigh`, `max`, or `auto` to use the model default. Available levels depend on the model. Takes precedence over `/effort` and the `effortLevel` setting. See [Adjust effort level](/en/model-config#adjust-effort-level) |

88| `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` | Override [session recap](/en/interactive-mode#session-recap) availability. Set to `0` to force recaps off regardless of the `/config` toggle. Set to `1` to force recaps on when [`awaySummaryEnabled`](/en/settings#available-settings) is `false`. Takes precedence over the setting and `/config` toggle |

89| `CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH` | Set to `1` to refresh plugin state at turn boundaries in [non-interactive mode](/en/headless) after a background install completes. Off by default because the refresh changes the system prompt mid-session, which invalidates [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) for that turn |

90| `CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING` | Set to `1` to force-enable fine-grained tool input streaming. Without this, the API buffers tool input parameters fully before sending delta events, which can delay display on large tool inputs. Anthropic API only: has no effect on Bedrock, Vertex, or Foundry |

91| `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION` | Set to `false` to disable prompt suggestions (the "Prompt suggestions" toggle in `/config`). These are the grayed-out predictions that appear in your prompt input after Claude responds. See [Prompt suggestions](/en/interactive-mode#prompt-suggestions) |

92| `CLAUDE_CODE_ENABLE_TASKS` | Set to `1` to enable the task tracking system in non-interactive mode (the `-p` flag). Tasks are on by default in interactive mode. See [Task list](/en/interactive-mode#task-list) |

93| `CLAUDE_CODE_ENABLE_TELEMETRY` | Set to `1` to enable OpenTelemetry data collection for metrics and logging. Required before configuring OTel exporters. See [Monitoring](/en/monitoring-usage) |

94| `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 |

95| `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` | Set to `1` to enable [agent teams](/en/agent-teams). Agent teams are experimental and disabled by default |

96| `CLAUDE_CODE_FILE_READ_MAX_OUTPUT_TOKENS` | Override the default token limit for file reads. Useful when you need to read larger files in full |

97| `CLAUDE_CODE_FORK_SUBAGENT` | Set to `1` to enable [forked subagents](/en/sub-agents#fork-the-current-conversation). A forked subagent inherits the full conversation context from the main session instead of starting fresh. When enabled, `/fork` spawns a forked subagent rather than acting as an alias for [`/branch`](/en/commands), and all subagent spawns run in the background. Interactive mode only |

98| `CLAUDE_CODE_GIT_BASH_PATH` | Windows only: path to the Git Bash executable (`bash.exe`). Use when Git Bash is installed but not in your PATH. See [Windows setup](/en/setup#set-up-on-windows) |

99| `CLAUDE_CODE_GLOB_HIDDEN` | Set to `false` to exclude dotfiles from results when Claude invokes the [Glob tool](/en/tools-reference). Included by default. Does not affect `@` file autocomplete, `ls`, Grep, or Read |

100| `CLAUDE_CODE_GLOB_NO_IGNORE` | Set to `false` to make the [Glob tool](/en/tools-reference) respect `.gitignore` patterns. By default, Glob returns all matching files including gitignored ones. Does not affect `@` file autocomplete, which has its own [`respectGitignore` setting](/en/settings#available-settings) |

101| `CLAUDE_CODE_GLOB_TIMEOUT_SECONDS` | Timeout in seconds for Glob tool file discovery. Defaults to 20 seconds on most platforms and 60 seconds on WSL |

102| `CLAUDE_CODE_HIDE_CWD` | Set to `1` to hide the working directory in the startup logo. Useful for screenshares or recordings where the path exposes your OS username |

103| `CLAUDE_CODE_IDE_HOST_OVERRIDE` | Override the host address used to connect to the IDE extension. By default Claude Code auto-detects the correct address, including WSL-to-Windows routing |

104| `CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL` | Skip auto-installation of IDE extensions. Equivalent to setting [`autoInstallIdeExtension`](/en/settings#global-config-settings) to `false` |

105| `CLAUDE_CODE_IDE_SKIP_VALID_CHECK` | Set to `1` to skip validation of IDE lockfile entries during connection. Use when auto-connect fails to find your IDE despite it running |

106| `CLAUDE_CODE_MAX_CONTEXT_TOKENS` | Override the context window size Claude Code assumes for the active model. Only takes effect when `DISABLE_COMPACT` is also set. Use this when routing to a model through `ANTHROPIC_BASE_URL` whose context window does not match the built-in size for its name |

107| `CLAUDE_CODE_MAX_OUTPUT_TOKENS` | Set the maximum number of output tokens for most requests. Defaults and caps vary by model; see [max output tokens](https://platform.claude.com/docs/en/about-claude/models/overview#latest-models-comparison). Increasing this value reduces the effective context window available before [auto-compaction](/en/costs#reduce-token-usage) triggers. |

108| `CLAUDE_CODE_MAX_RETRIES` | Override the number of times to retry failed API requests (default: 10) |

109| `CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY` | Maximum number of read-only tools and subagents that can execute in parallel (default: 10). Higher values increase parallelism but consume more resources |

110| `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. |

111| `CLAUDE_CODE_NO_FLICKER` | Set to `1` to enable [fullscreen rendering](/en/fullscreen), a research preview that reduces flicker and keeps memory flat in long conversations. Equivalent to the [`tui`](/en/settings#available-settings) setting; you can also switch with `/tui fullscreen` |

112| `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 |

113| `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 |

114| `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`](/en/authentication#generate-a-long-lived-token) |

115| `CLAUDE_CODE_OTEL_FLUSH_TIMEOUT_MS` | Timeout in milliseconds for flushing pending OpenTelemetry spans (default: 5000). See [Monitoring](/en/monitoring-usage) |

116| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic OpenTelemetry headers in milliseconds (default: 1740000 / 29 minutes). See [Dynamic headers](/en/monitoring-usage#dynamic-headers) |

117| `CLAUDE_CODE_OTEL_SHUTDOWN_TIMEOUT_MS` | Timeout in milliseconds for the OpenTelemetry exporter to finish on shutdown (default: 2000). Increase if metrics are dropped at exit. See [Monitoring](/en/monitoring-usage) |

118| `CLAUDE_CODE_PERFORCE_MODE` | Set to `1` to enable Perforce-aware write protection. When set, Edit, Write, and NotebookEdit fail with a `p4 edit <file>` hint if the target file lacks the owner-write bit, which Perforce clears on synced files until `p4 edit` opens them. This prevents Claude Code from bypassing Perforce change tracking |

119| `CLAUDE_CODE_PLUGIN_CACHE_DIR` | Override the plugins root directory. Despite the name, this sets the parent directory, not the cache itself: marketplaces and the plugin cache live in subdirectories under this path. Defaults to `~/.claude/plugins` |

120| `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) |

121| `CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE` | Set to `1` to keep the existing marketplace cache when a `git pull` fails instead of wiping and re-cloning. Useful in offline or airgapped environments where re-cloning would fail the same way. See [Marketplace updates fail in offline environments](/en/plugin-marketplaces#marketplace-updates-fail-in-offline-environments) |

122| `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) |

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

124| `CLAUDE_CODE_REMOTE` | Set automatically to `true` when Claude Code is running as a [cloud session](/en/claude-code-on-the-web). Read this from a hook or setup script to detect whether you are in a cloud environment |

125| `CLAUDE_CODE_REMOTE_SESSION_ID` | Set automatically in [cloud sessions](/en/claude-code-on-the-web) to the current session's ID. Read this to construct a link back to the session transcript. See [Link artifacts back to the session](/en/claude-code-on-the-web#link-artifacts-back-to-the-session) |

126| `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` | Set to `1` to automatically resume if the previous session ended mid-turn. Used in SDK mode so the model continues without requiring the SDK to re-send the prompt |

127| `CLAUDE_CODE_SCRIPT_CAPS` | JSON object limiting how many times specific scripts may be invoked per session when `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` is set. Keys are substrings matched against the command text; values are integer call limits. For example, `{"deploy.sh": 2}` allows `deploy.sh` to be called at most twice. Matching is substring-based so shell-expansion tricks like `./scripts/deploy.sh $(evil)` still count against the cap. Runtime fan-out via `xargs` or `find -exec` is not detected; this is a defense-in-depth control |

128| `CLAUDE_CODE_SCROLL_SPEED` | Set the mouse wheel scroll multiplier in [fullscreen rendering](/en/fullscreen#mouse-wheel-scrolling). Accepts values from 1 to 20. Set to `3` to match `vim` if your terminal sends one wheel event per notch without amplification |

129| `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` | Override the time budget in milliseconds for [SessionEnd](/en/hooks#sessionend) hooks. Applies to session exit, `/clear`, and switching sessions via interactive `/resume`. By default the budget is 1.5 seconds, automatically raised to the highest per-hook `timeout` configured in settings files, up to 60 seconds. Timeouts on plugin-provided hooks do not raise the budget |

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

131| `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>` |

132| `CLAUDE_CODE_SIMPLE` | Set to `1` to run with a minimal system prompt and only the Bash, file read, and file edit tools. MCP tools from `--mcp-config` are still available. Disables auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. The [`--bare`](/en/headless#start-faster-with-bare-mode) CLI flag sets this |

133| `CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT` | Set to `1` to use the minimal system prompt and collapsed tool descriptions from `CLAUDE_CODE_SIMPLE` without the other simple-mode changes. The full tool set, hooks, MCP servers, and CLAUDE.md discovery remain enabled |

134| `CLAUDE_CODE_SKIP_BEDROCK_AUTH` | Skip AWS authentication for Bedrock (for example, when using an LLM gateway) |

135| `CLAUDE_CODE_SKIP_FOUNDRY_AUTH` | Skip Azure authentication for Microsoft Foundry (for example, when using an LLM gateway) |

136| `CLAUDE_CODE_SKIP_MANTLE_AUTH` | Skip AWS authentication for Bedrock Mantle (for example, when using an LLM gateway) |

137| `CLAUDE_CODE_SKIP_PROMPT_HISTORY` | Set to `1` to skip writing prompt history and session transcripts to disk. Sessions started with this variable set do not appear in `--resume`, `--continue`, or up-arrow history. Useful for ephemeral scripted sessions |

138| `CLAUDE_CODE_SKIP_VERTEX_AUTH` | Skip Google authentication for Vertex (for example, when using an LLM gateway) |

139| `CLAUDE_CODE_SUBAGENT_MODEL` | See [Model configuration](/en/model-config) |

140| `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` | Set to `1` to strip Anthropic and cloud provider credentials from subprocess environments (Bash tool, hooks, MCP stdio servers). The parent Claude process keeps these credentials for API calls, but child processes cannot read them, reducing exposure to prompt injection attacks that attempt to exfiltrate secrets via shell expansion. On Linux, this also runs Bash subprocesses in an isolated PID namespace so they cannot read host process environments via `/proc`; as a side effect, `ps`, `pgrep`, and `kill` cannot see or signal host processes. `claude-code-action` sets this automatically when `allowed_non_write_users` is configured |

141| `CLAUDE_CODE_SYNC_PLUGIN_INSTALL` | Set to `1` in non-interactive mode (the `-p` flag) to wait for plugin installation to complete before the first query. Without this, plugins install in the background and may not be available on the first turn. Combine with `CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS` to bound the wait |

142| `CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS` | Timeout in milliseconds for synchronous plugin installation. When exceeded, Claude Code proceeds without plugins and logs an error. No default: without this variable, synchronous installation waits until complete |

143| `CLAUDE_CODE_SYNTAX_HIGHLIGHT` | Set to `false` to disable syntax highlighting in diff output. Useful when colors interfere with your terminal setup |

144| `CLAUDE_CODE_TASK_LIST_ID` | Share a task list across sessions. Set the same ID in multiple Claude Code instances to coordinate on a shared task list. See [Task list](/en/interactive-mode#task-list) |

145| `CLAUDE_CODE_TEAM_NAME` | Name of the agent team this teammate belongs to. Set automatically on [agent team](/en/agent-teams) members |

146| `CLAUDE_CODE_TMPDIR` | Override the temp directory used for internal temp files. Claude Code appends `/claude-{uid}/` (Unix) or `/claude/` (Windows) to this path. Default: `/tmp` on macOS, `os.tmpdir()` on Linux/Windows |

147| `CLAUDE_CODE_TMUX_TRUECOLOR` | Set to `1` to allow 24-bit truecolor output inside tmux. By default, Claude Code clamps to 256 colors when `$TMUX` is set because tmux does not pass through truecolor escape sequences unless configured to. Set this after adding `set -ga terminal-overrides ',*:Tc'` to your `~/.tmux.conf`. See [Terminal configuration](/en/terminal-config) for other tmux settings |

148| `CLAUDE_CODE_USE_BEDROCK` | Use [Bedrock](/en/amazon-bedrock) |

149| `CLAUDE_CODE_USE_FOUNDRY` | Use [Microsoft Foundry](/en/microsoft-foundry) |

150| `CLAUDE_CODE_USE_MANTLE` | Use the Bedrock [Mantle endpoint](/en/amazon-bedrock#use-the-mantle-endpoint) |

151| `CLAUDE_CODE_USE_POWERSHELL_TOOL` | Controls the PowerShell tool. On Windows, the tool is rolling out progressively: set to `1` to opt in or `0` to opt out. On Linux, macOS, and WSL, set to `1` to enable it, which requires `pwsh` on your `PATH`. When enabled on Windows, Claude can run PowerShell commands natively instead of routing through Git Bash. See [PowerShell tool](/en/tools-reference#powershell-tool) |

152| `CLAUDE_CODE_USE_VERTEX` | Use [Vertex](/en/google-vertex-ai) |

153| `CLAUDE_CONFIG_DIR` | Override the configuration directory (default: `~/.claude`). All settings, credentials, session history, and plugins are stored under this path. Useful for running multiple accounts side by side: for example, `alias claude-work='CLAUDE_CONFIG_DIR=~/.claude-work claude'` |

154| `CLAUDE_ENABLE_BYTE_WATCHDOG` | Set to `1` to force-enable the byte-level streaming idle watchdog, or set to `0` to force-disable it. When unset, the watchdog is enabled by default for Anthropic API connections. The byte watchdog aborts a connection when no bytes arrive on the wire for the duration set by `CLAUDE_STREAM_IDLE_TIMEOUT_MS`, with a minimum of 5 minutes, independent of the event-level watchdog |

155| `CLAUDE_ENABLE_STREAM_WATCHDOG` | Set to `1` to enable the event-level streaming idle watchdog. Off by default. For Bedrock, Vertex, and Foundry, this is the only idle watchdog available. Configure the timeout with `CLAUDE_STREAM_IDLE_TIMEOUT_MS` |

156| `CLAUDE_ENV_FILE` | Path to a shell script whose contents Claude Code runs before each Bash command in the same shell process, so exports in the file are visible to the command. Use to persist virtualenv or conda activation across commands. Also populated dynamically by [SessionStart](/en/hooks#persist-environment-variables), [CwdChanged](/en/hooks#cwdchanged), and [FileChanged](/en/hooks#filechanged) hooks |

157| `CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX` | Prefix for auto-generated [Remote Control](/en/remote-control) session names when no explicit name is provided. Defaults to your machine's hostname, producing names like `myhost-graceful-unicorn`. The `--remote-control-session-name-prefix` CLI flag sets the same value for a single invocation |

158| `CLAUDE_STREAM_IDLE_TIMEOUT_MS` | Timeout in milliseconds before the streaming idle watchdog closes a stalled connection. For the byte-level watchdog on the Anthropic API: default and minimum `300000` (5 minutes); lower values are silently clamped to absorb extended thinking pauses and proxy buffering. For the event-level watchdog: default `90000` (90 seconds), no minimum. For third-party providers, requires `CLAUDE_ENABLE_STREAM_WATCHDOG=1` |

159| `DISABLE_AUTOUPDATER` | Set to `1` to disable automatic background updates. Manual `claude update` still works. Use `DISABLE_UPDATES` to block both |

160| `DISABLE_AUTO_COMPACT` | Set to `1` to disable automatic compaction when approaching the context limit. The manual `/compact` command remains available. Use when you want explicit control over when compaction occurs |

161| `DISABLE_COMPACT` | Set to `1` to disable all compaction: both automatic compaction and the manual `/compact` command |

162| `DISABLE_COST_WARNINGS` | Set to `1` to disable cost warning messages |

163| `DISABLE_DOCTOR_COMMAND` | Set to `1` to hide the `/doctor` command. Useful for managed deployments where users should not run installation diagnostics |

164| `DISABLE_ERROR_REPORTING` | Set to `1` to opt out of Sentry error reporting |

165| `DISABLE_EXTRA_USAGE_COMMAND` | Set to `1` to hide the `/extra-usage` command that lets users purchase additional usage beyond rate limits |

166| `DISABLE_FEEDBACK_COMMAND` | Set to `1` to disable the `/feedback` command. The older name `DISABLE_BUG_COMMAND` is also accepted |

167| `DISABLE_INSTALLATION_CHECKS` | Set to `1` to disable installation warnings. Use only when manually managing the installation location, as this can mask issues with standard installations |

168| `DISABLE_INSTALL_GITHUB_APP_COMMAND` | Set to `1` to hide the `/install-github-app` command. Already hidden when using third-party providers (Bedrock, Vertex, or Foundry) |

169| `DISABLE_INTERLEAVED_THINKING` | Set to `1` to prevent sending the interleaved-thinking beta header. Useful when your LLM gateway or provider does not support [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking#interleaved-thinking) |

170| `DISABLE_LOGIN_COMMAND` | Set to `1` to hide the `/login` command. Useful when authentication is handled externally via API keys or `apiKeyHelper` |

171| `DISABLE_LOGOUT_COMMAND` | Set to `1` to hide the `/logout` command |

172| `DISABLE_PROMPT_CACHING` | Set to `1` to disable prompt caching for all models (takes precedence over per-model settings) |

173| `DISABLE_PROMPT_CACHING_HAIKU` | Set to `1` to disable prompt caching for Haiku models |

174| `DISABLE_PROMPT_CACHING_OPUS` | Set to `1` to disable prompt caching for Opus models |

175| `DISABLE_PROMPT_CACHING_SONNET` | Set to `1` to disable prompt caching for Sonnet models |

176| `DISABLE_TELEMETRY` | Set to `1` to opt out of Statsig telemetry (note that Statsig events do not include user data like code, file paths, or bash commands) |

177| `DISABLE_UPDATES` | Set to `1` to block all updates including manual `claude update` and `claude install`. Stricter than `DISABLE_AUTOUPDATER`. Use when distributing Claude Code through your own channels and users should not self-update |

178| `DISABLE_UPGRADE_COMMAND` | Set to `1` to hide the `/upgrade` command |

179| `ENABLE_CLAUDEAI_MCP_SERVERS` | Set to `false` to disable [claude.ai MCP servers](/en/mcp#use-mcp-servers-from-claude-ai) in Claude Code. Enabled by default for logged-in users |

180| `ENABLE_PROMPT_CACHING_1H` | Set to `1` to request a 1-hour prompt cache TTL instead of the default 5 minutes. Intended for API key, [Bedrock](/en/amazon-bedrock), [Vertex](/en/google-vertex-ai), and [Foundry](/en/microsoft-foundry) users. Subscription users receive 1-hour TTL automatically. 1-hour cache writes are billed at a higher rate |

181| `ENABLE_PROMPT_CACHING_1H_BEDROCK` | Deprecated. Use `ENABLE_PROMPT_CACHING_1H` instead |

182| `ENABLE_TOOL_SEARCH` | Controls [MCP tool search](/en/mcp#scale-with-mcp-tool-search). Unset: all MCP tools deferred by default, but loaded upfront on Vertex AI or when `ANTHROPIC_BASE_URL` points to a non-first-party host. Values: `true` (always defer including proxies and Vertex AI), `auto` (threshold mode: load upfront if tools fit within 10% of context), `auto:N` (custom threshold, e.g., `auto:5` for 5%), `false` (load all upfront) |

183| `FALLBACK_FOR_ALL_PRIMARY_MODELS` | Set to any non-empty value to trigger fallback to [`--fallback-model`](/en/cli-reference#cli-flags) after repeated overload errors on any primary model. By default, only Opus models trigger the fallback |

184| `FORCE_AUTOUPDATE_PLUGINS` | Set to `1` to force plugin auto-updates even when the main auto-updater is disabled via `DISABLE_AUTOUPDATER` |

185| `FORCE_PROMPT_CACHING_5M` | Set to `1` to force the 5-minute prompt cache TTL even when 1-hour TTL would otherwise apply. Overrides `ENABLE_PROMPT_CACHING_1H` |

186| `HTTP_PROXY` | Specify HTTP proxy server for network connections |

187| `HTTPS_PROXY` | Specify HTTPS proxy server for network connections |

188| `IS_DEMO` | Set to `1` to enable demo mode: hides your email and organization name from the header and `/status` output, and skips onboarding. Useful when streaming or recording a session |

189| `MAX_MCP_OUTPUT_TOKENS` | Maximum number of tokens allowed in MCP tool responses. Claude Code displays a warning when output exceeds 10,000 tokens. Tools that declare [`anthropic/maxResultSizeChars`](/en/mcp#raise-the-limit-for-a-specific-tool) use that character limit for text content instead, but image content from those tools is still subject to this variable (default: 25000) |

190| `MAX_STRUCTURED_OUTPUT_RETRIES` | Number of times to retry when the model's response fails validation against the [`--json-schema`](/en/cli-reference#cli-flags) in non-interactive mode (the `-p` flag). Defaults to 5 |

191| `MAX_THINKING_TOKENS` | Override the [extended thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking) token budget. The ceiling is the model's [max output tokens](https://platform.claude.com/docs/en/about-claude/models/overview#latest-models-comparison) minus one. Set to `0` to disable thinking entirely. On models with [adaptive reasoning](/en/model-config#adjust-effort-level), the budget is ignored unless adaptive reasoning is disabled via `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` |

192| `MCP_CLIENT_SECRET` | OAuth client secret for MCP servers that require [pre-configured credentials](/en/mcp#use-pre-configured-oauth-credentials). Avoids the interactive prompt when adding a server with `--client-secret` |

193| `MCP_CONNECTION_NONBLOCKING` | Set to `true` in non-interactive mode (`-p`) to skip the MCP connection wait entirely. Useful for scripted pipelines where MCP tools are not needed. Without this variable, the first query waits up to 5 seconds for `--mcp-config` server connections |

194| `MCP_OAUTH_CALLBACK_PORT` | Fixed port for the OAuth redirect callback, as an alternative to `--callback-port` when adding an MCP server with [pre-configured credentials](/en/mcp#use-pre-configured-oauth-credentials) |

195| `MCP_REMOTE_SERVER_CONNECTION_BATCH_SIZE` | Maximum number of remote MCP servers (HTTP/SSE) to connect in parallel during startup (default: 20) |

196| `MCP_SERVER_CONNECTION_BATCH_SIZE` | Maximum number of local MCP servers (stdio) to connect in parallel during startup (default: 3) |

197| `MCP_TIMEOUT` | Timeout in milliseconds for MCP server startup (default: 30000, or 30 seconds) |

198| `MCP_TOOL_TIMEOUT` | Timeout in milliseconds for MCP tool execution (default: 100000000, about 28 hours) |

199| `NO_PROXY` | List of domains and IPs to which requests will be directly issued, bypassing proxy |

200| `OTEL_LOG_RAW_API_BODIES` | Emit Anthropic Messages API request and response JSON as `api_request_body` / `api_response_body` log events. Set to `1` for inline bodies truncated at 60 KB, or `file:<dir>` to write untruncated bodies to disk and emit a `body_ref` path instead. Disabled by default; bodies include the entire conversation history. See [Monitoring](/en/monitoring-usage#api-request-body-event) |

201| `OTEL_LOG_TOOL_CONTENT` | Set to `1` to include tool input and output content in OpenTelemetry span events. Disabled by default to protect sensitive data. See [Monitoring](/en/monitoring-usage) |

202| `OTEL_LOG_TOOL_DETAILS` | Set to `1` to include tool input arguments, MCP server names, raw error strings on tool failures, and other tool details in OpenTelemetry traces and logs. Disabled by default to protect PII. See [Monitoring](/en/monitoring-usage) |

203| `OTEL_LOG_USER_PROMPTS` | Set to `1` to include user prompt text in OpenTelemetry traces and logs. Disabled by default (prompts are redacted). See [Monitoring](/en/monitoring-usage) |

204| `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` | Set to `false` to exclude account UUID from metrics attributes (default: included). See [Monitoring](/en/monitoring-usage) |

205| `OTEL_METRICS_INCLUDE_SESSION_ID` | Set to `false` to exclude session ID from metrics attributes (default: included). See [Monitoring](/en/monitoring-usage) |

206| `OTEL_METRICS_INCLUDE_VERSION` | Set to `true` to include Claude Code version in metrics attributes (default: excluded). See [Monitoring](/en/monitoring-usage) |

207| `SLASH_COMMAND_TOOL_CHAR_BUDGET` | Override the character budget for skill metadata shown to the [Skill tool](/en/skills#control-who-invokes-a-skill). The budget scales dynamically at 1% of the context window, with a fallback of 8,000 characters. Legacy name kept for backwards compatibility |

208| `TASK_MAX_OUTPUT_LENGTH` | Maximum number of characters in [subagent](/en/sub-agents) output before truncation (default: 32000, maximum: 160000). When truncated, the full output is saved to disk and the path is included in the truncated response |

209| `USE_BUILTIN_RIPGREP` | Set to `0` to use system-installed `rg` instead of `rg` included with Claude Code |

210| `VERTEX_REGION_CLAUDE_3_5_HAIKU` | Override region for Claude 3.5 Haiku when using Vertex AI |

211| `VERTEX_REGION_CLAUDE_3_5_SONNET` | Override region for Claude 3.5 Sonnet when using Vertex AI |

212| `VERTEX_REGION_CLAUDE_3_7_SONNET` | Override region for Claude 3.7 Sonnet when using Vertex AI |

213| `VERTEX_REGION_CLAUDE_4_0_OPUS` | Override region for Claude 4.0 Opus when using Vertex AI |

214| `VERTEX_REGION_CLAUDE_4_0_SONNET` | Override region for Claude 4.0 Sonnet when using Vertex AI |

215| `VERTEX_REGION_CLAUDE_4_1_OPUS` | Override region for Claude 4.1 Opus when using Vertex AI |

216| `VERTEX_REGION_CLAUDE_4_5_OPUS` | Override region for Claude Opus 4.5 when using Vertex AI |

217| `VERTEX_REGION_CLAUDE_4_5_SONNET` | Override region for Claude Sonnet 4.5 when using Vertex AI |

218| `VERTEX_REGION_CLAUDE_4_6_OPUS` | Override region for Claude Opus 4.6 when using Vertex AI |

219| `VERTEX_REGION_CLAUDE_4_6_SONNET` | Override region for Claude Sonnet 4.6 when using Vertex AI |

220| `VERTEX_REGION_CLAUDE_4_7_OPUS` | {/* min-version: 2.1.111 */}Override region for Claude Opus 4.7 when using Vertex AI |

221| `VERTEX_REGION_CLAUDE_HAIKU_4_5` | Override region for Claude Haiku 4.5 when using Vertex AI |

222 

223Standard OpenTelemetry exporter variables (`OTEL_METRICS_EXPORTER`, `OTEL_LOGS_EXPORTER`, `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_PROTOCOL`, `OTEL_EXPORTER_OTLP_HEADERS`, `OTEL_METRIC_EXPORT_INTERVAL`, `OTEL_RESOURCE_ATTRIBUTES`, and signal-specific variants) are also supported. See [Monitoring](/en/monitoring-usage) for configuration details.

224 

225## See also

226 

227* [Settings](/en/settings): configure environment variables in `settings.json` so they apply to every session

228* [CLI reference](/en/cli-reference): launch-time flags

229* [Network configuration](/en/network-config): proxy and TLS setup

230* [Monitoring](/en/monitoring-usage): OpenTelemetry configuration

errors.md +535 −0 added

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# Error reference

6 

7> Look up Claude Code runtime error messages with what each one means and how to fix it.

8 

9This page lists runtime errors Claude Code displays and how to recover from each one, plus what to check when responses seem off without an error. For installation errors such as `command not found` or TLS failures during setup, see [Troubleshooting](/en/troubleshooting).

10 

11These errors and recovery commands apply across the CLI, the [Desktop app](/en/desktop), and [Claude Code on the web](/en/claude-code-on-the-web), since all three wrap the same Claude Code CLI. For surface-specific issues, see the troubleshooting section on that surface's page.

12 

13<Note>

14 Claude Code calls the Claude API for model responses, so most runtime errors map to an underlying API error code. This page covers what each error means inside Claude Code and how to recover. For the raw HTTP status code definitions, see the [Claude Platform error reference](https://platform.claude.com/docs/en/api/errors).

15</Note>

16 

17## Find your error

18 

19Match the message you see in your terminal to a section below.

20 

21| Message | Section |

22| :----------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- |

23| `API Error: 500 ... Internal server error` | [Server errors](#api-error-500-internal-server-error) |

24| `API Error: Repeated 529 Overloaded errors` | [Server errors](#api-error-repeated-529-overloaded-errors) |

25| `Request timed out` | [Server errors](#request-timed-out), or [Network](#unable-to-connect-to-api) if the message mentions your internet connection |

26| `<model> is temporarily unavailable, so auto mode cannot determine the safety of...` | [Server errors](#auto-mode-cannot-determine-the-safety-of-an-action) |

27| `You've hit your session limit` / `You've hit your weekly limit` | [Usage limits](#youve-hit-your-session-limit) |

28| `Server is temporarily limiting requests` | [Usage limits](#server-is-temporarily-limiting-requests) |

29| `Request rejected (429)` | [Usage limits](#request-rejected-429) |

30| `Credit balance is too low` | [Usage limits](#credit-balance-is-too-low) |

31| `Not logged in · Please run /login` | [Authentication](#not-logged-in) |

32| `Invalid API key` | [Authentication](#invalid-api-key) |

33| `This organization has been disabled` | [Authentication](#this-organization-has-been-disabled) |

34| `OAuth token revoked` / `OAuth token has expired` | [Authentication](#oauth-token-revoked-or-expired) |

35| `does not meet scope requirement user:profile` | [Authentication](#oauth-scope-requirement) |

36| `Unable to connect to API` | [Network](#unable-to-connect-to-api) |

37| `SSL certificate verification failed` | [Network](#ssl-certificate-errors) |

38| `Prompt is too long` | [Request errors](#prompt-is-too-long) |

39| `Error during compaction: Conversation too long` | [Request errors](#error-during-compaction-conversation-too-long) |

40| `Request too large` | [Request errors](#request-too-large) |

41| `Image was too large` | [Request errors](#image-was-too-large) |

42| `PDF too large` / `PDF is password protected` | [Request errors](#pdf-errors) |

43| `Extra inputs are not permitted` | [Request errors](#extra-inputs-are-not-permitted) |

44| `There's an issue with the selected model` | [Request errors](#theres-an-issue-with-the-selected-model) |

45| `Claude Opus is not available with the Claude Pro plan` | [Request errors](#claude-opus-is-not-available-with-the-claude-pro-plan) |

46| `thinking.type.enabled is not supported for this model` | [Request errors](#thinking-type-enabled-is-not-supported-for-this-model) |

47| `max_tokens must be greater than thinking.budget_tokens` | [Request errors](#thinking-budget-exceeds-output-limit) |

48| `API Error: 400 due to tool use concurrency issues` | [Request errors](#tool-use-or-thinking-block-mismatch) |

49| Responses seem lower quality than usual | [Response quality](#responses-seem-lower-quality-than-usual) |

50 

51## Automatic retries

52 

53Claude Code retries transient failures before showing you an error. Server errors, overloaded responses, request timeouts, temporary 429 throttles, and dropped connections are all retried up to 10 times with exponential backoff. While retrying, the spinner shows a `Retrying in Ns · attempt x/y` countdown.

54 

55When you see one of the errors on this page, those retries have already been exhausted. You can tune the behavior with two environment variables:

56 

57| Variable | Default | Effect |

58| :---------------------------------------- | :------ | :------------------------------------------------------------------------------------------------------------------- |

59| [`CLAUDE_CODE_MAX_RETRIES`](/en/env-vars) | 10 | Number of retry attempts. Lower it to surface failures faster in scripts; raise it to wait through longer incidents. |

60| [`API_TIMEOUT_MS`](/en/env-vars) | 600000 | Per-request timeout in milliseconds. Raise it for slow networks or proxies. |

61 

62## Server errors

63 

64These errors come from Anthropic infrastructure rather than your account or request.

65 

66### API Error: 500 Internal server error

67 

68Claude Code shows the raw API response body for any 5xx status. The example below shows a 500 response:

69 

70```text theme={null}

71API Error: 500 {"type":"error","error":{"type":"api_error","message":"Internal server error"}} · check status.claude.com

72```

73 

74This indicates an unexpected failure inside the API. It is not caused by your prompt, settings, or account.

75 

76**What to do:**

77 

78* Check [status.claude.com](https://status.claude.com) for active incidents

79* Wait a minute, then send your message again. Your original message is still in the conversation, so for a long prompt you can type `try again` instead of pasting the whole thing.

80* If the error persists with no posted incident, run `/feedback` so Anthropic can investigate with your request details. See [Report an error](#report-an-error) if `/feedback` is unavailable on your provider.

81 

82### API Error: Repeated 529 Overloaded errors

83 

84The API is temporarily at capacity across all users. Claude Code has already retried several times before showing this message:

85 

86```text theme={null}

87API Error: Repeated 529 Overloaded errors · check status.claude.com

88```

89 

90A 529 is not your usage limit and does not count against your quota.

91 

92**What to do:**

93 

94* Check [status.claude.com](https://status.claude.com) for capacity notices

95* Try again in a few minutes

96* Run `/model` and switch to a different model to keep working, since capacity is tracked per model. Claude Code prompts you to do this when one model is under particularly high load, for example `Opus is experiencing high load, please use /model to switch to Sonnet`.

97 

98### Request timed out

99 

100The API did not respond before the connection deadline.

101 

102```text theme={null}

103Request timed out

104```

105 

106This can happen during periods of high load or when a very large response is being generated. The default request timeout is 10 minutes.

107 

108**What to do:**

109 

110* Retry the request

111* For long-running tasks, break the work into smaller prompts

112* If a slow network or proxy is the cause, raise `API_TIMEOUT_MS` as described in [Automatic retries](#automatic-retries)

113* If timeouts are frequent and your network is otherwise healthy, see [Network and connection errors](#network-and-connection-errors) below

114 

115### Auto mode cannot determine the safety of an action

116 

117The model that [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) uses to classify actions is overloaded, so auto mode blocked the action instead of approving it unchecked.

118 

119```text theme={null}

120<model> is temporarily unavailable, so auto mode cannot determine the safety of <tool> right now. Wait briefly and then try this action again.

121```

122 

123Reads, searches, and edits inside your working directory skip the classifier, so they keep working during the outage.

124 

125**What to do:**

126 

127* Retry after a few seconds; Claude sees the same message and usually retries on its own

128* If retries keep failing, continue with read-only tasks and come back to the blocked action later

129* This is transient and unrelated to [auto mode eligibility](/en/permission-modes#eliminate-prompts-with-auto-mode); you do not need to change settings

130 

131## Usage limits

132 

133These errors mean a quota tied to your account or plan has been reached. They are distinct from [server errors](#server-errors), which affect everyone.

134 

135### You've hit your session limit

136 

137Subscription plans include a rolling usage allowance. When it runs out you see one of these messages:

138 

139```text theme={null}

140You've hit your session limit · resets 3:45pm

141You've hit your weekly limit · resets Mon 12:00am

142You've hit your Opus limit · resets 3:45pm

143```

144 

145Claude Code blocks further requests until the reset time shown in the message.

146 

147**What to do:**

148 

149* Wait for the reset time shown in the error

150* Run `/usage` to see your plan limits and when they reset

151* Run `/extra-usage` to buy additional usage on Pro and Max, or to request it from your admin on Team and Enterprise. See [Extra usage for paid plans](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) for how this is billed.

152* To upgrade your plan for higher base limits, see [claude.com/pricing](https://claude.com/pricing)

153 

154To watch your remaining allowance before you hit the limit, add the `rate_limits` fields to a [custom status line](/en/statusline#rate-limit-usage), or in the Desktop app click the [usage ring](/en/desktop#check-usage) next to the model picker.

155 

156### Server is temporarily limiting requests

157 

158The API applied a short-lived throttle that is unrelated to your plan quota.

159 

160```text theme={null}

161API Error: Server is temporarily limiting requests (not your usage limit)

162```

163 

164This is [retried automatically](#automatic-retries) before being shown.

165 

166**What to do:**

167 

168* Wait briefly and try again

169* Check [status.claude.com](https://status.claude.com) if it persists

170 

171### Request rejected (429)

172 

173You have hit the rate limit configured for your API key, Amazon Bedrock project, or Google Vertex AI project.

174 

175```text theme={null}

176API Error: Request rejected (429) · this may be a temporary capacity issue

177```

178 

179**What to do:**

180 

181* Run `/status` and confirm the active credential is the one you expect. A stray `ANTHROPIC_API_KEY` in your environment can route requests through a low-tier key instead of your subscription.

182* Check your provider console for the active limits and request a higher tier if needed

183* For Anthropic API keys, see the [rate limits reference](https://platform.claude.com/docs/en/api/rate-limits) for how tiers work and how to set per-workspace caps

184* Reduce concurrency: lower [`CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY`](/en/env-vars), avoid running many parallel subagents, or switch to a smaller model with `/model` for high-volume scripted runs

185 

186### Credit balance is too low

187 

188Your Console organization has run out of prepaid credits.

189 

190```text theme={null}

191Credit balance is too low

192```

193 

194**What to do:**

195 

196* Add credits at [platform.claude.com/settings/billing](https://platform.claude.com/settings/billing), and consider enabling auto-reload there so the balance refills before it hits zero

197* Switch to subscription authentication with `/login` if you have a Pro, Max, Team, or Enterprise plan

198* Set per-workspace spend caps in the Console to prevent a single project from draining the org balance. See [Manage costs effectively](/en/costs).

199 

200## Authentication errors

201 

202These errors mean Claude Code cannot prove who you are to the API. Run `/status` at any time to see which credential is currently active.

203 

204### Not logged in

205 

206No valid credential is available for this session.

207 

208```text theme={null}

209Not logged in · Please run /login

210```

211 

212**What to do:**

213 

214* Run `/login` to authenticate with your Claude subscription or Console account

215* If you expected an environment variable to authenticate you, confirm `ANTHROPIC_API_KEY` is set and exported in the shell where you launched `claude`

216* For CI or automation where interactive login is not possible, configure an [`apiKeyHelper`](/en/settings#available-settings) script that fetches a key at startup

217* See [Authentication precedence](/en/authentication#authentication-precedence) to understand which credential wins when several are present

218 

219If you are prompted to log in repeatedly, see [Not logged in or token expired](/en/troubleshooting#not-logged-in-or-token-expired) for system clock and macOS Keychain fixes.

220 

221### Invalid API key

222 

223The `ANTHROPIC_API_KEY` environment variable or `apiKeyHelper` script returned a key the API rejected.

224 

225```text theme={null}

226Invalid API key · Fix external API key

227```

228 

229**What to do:**

230 

231* Check for typos and confirm the key has not been revoked in the [Console](https://platform.claude.com/settings/keys)

232* Run `env | grep ANTHROPIC` in the same shell. Tools like direnv, dotenv shell plugins, and IDE terminals can load a stale key from a `.env` file in your project without you setting it explicitly.

233* Unset `ANTHROPIC_API_KEY` and run `/login` to use subscription auth instead

234* If the key comes from an [`apiKeyHelper`](/en/settings#available-settings) script, run the script directly to confirm it prints a valid key on stdout

235* Run `/status` to confirm which credential source Claude Code is actually using

236 

237### This organization has been disabled

238 

239A stale `ANTHROPIC_API_KEY` from a disabled Console organization is overriding your subscription login.

240 

241```text theme={null}

242Your ANTHROPIC_API_KEY belongs to a disabled organization · Unset the environment variable to use your other credentials

243API Error: 400 ... This organization has been disabled.

244```

245 

246Environment variables take precedence over `/login`, so a key exported in your shell profile or loaded from a `.env` file is used even when you have a working Pro or Max subscription. In non-interactive mode (`-p`), the key is always used when present.

247 

248**What to do:**

249 

250* Unset `ANTHROPIC_API_KEY` in the current shell and remove it from your shell profile, then relaunch `claude`

251* Run `/status` afterward to confirm the active credential is your subscription

252* If no environment variable is set and the error persists, the disabled organization is the one tied to your `/login`. Contact support or sign in with a different account.

253 

254### OAuth token revoked or expired

255 

256Your saved login is no longer valid. A revoked token means you signed out everywhere or an admin removed access; an expired token means the automatic refresh failed mid-session.

257 

258```text theme={null}

259OAuth token revoked · Please run /login

260OAuth token has expired · Please run /login

261API Error: 401 ... authentication_error

262```

263 

264**What to do:**

265 

266* Run `/login` to sign in again

267* If the error returns within the same session after re-authenticating, run `/logout` first to fully clear the stored token, then `/login`

268* For repeated prompts to log in across launches, see the system clock and macOS Keychain checks in [Troubleshooting](/en/troubleshooting#not-logged-in-or-token-expired)

269* For other failures including `403 Forbidden` and OAuth browser issues, see [Permissions and authentication](/en/troubleshooting#permissions-and-authentication)

270 

271### OAuth scope requirement

272 

273The stored token predates a permission scope that a newer feature needs. You see this most often from `/usage` and the status line usage indicator:

274 

275```text theme={null}

276OAuth token does not meet scope requirement: user:profile

277```

278 

279**What to do:**

280 

281* Run `/login` to mint a new token with the current scopes. You do not need to log out first.

282 

283## Network and connection errors

284 

285These errors mean Claude Code could not reach the API at all. They almost always originate in your local network, proxy, or firewall rather than Anthropic infrastructure.

286 

287### Unable to connect to API

288 

289The TCP connection to the API failed or never completed.

290 

291```text theme={null}

292Unable to connect to API. Check your internet connection

293Unable to connect to API (ECONNREFUSED)

294Unable to connect to API (ECONNRESET)

295Unable to connect to API (ETIMEDOUT)

296fetch failed

297Request timed out. Check your internet connection and proxy settings

298```

299 

300Common causes include no internet access, a VPN that blocks `api.anthropic.com`, or a required corporate proxy that is not configured.

301 

302**What to do:**

303 

304* Confirm you can reach the API host from the same shell by running `curl -I https://api.anthropic.com`. On Windows PowerShell use `curl.exe -I https://api.anthropic.com` so the built-in `Invoke-WebRequest` alias is not used.

305* If you are behind a corporate proxy, set `HTTPS_PROXY` before launching Claude Code and see [Network configuration](/en/network-config)

306* If you route through an LLM gateway or relay, set [`ANTHROPIC_BASE_URL`](/en/env-vars) to its address. See [LLM gateway configuration](/en/llm-gateway) for setup.

307* Ensure your firewall allows the hosts listed in [Network access requirements](/en/network-config#network-access-requirements)

308* Intermittent failures are [retried automatically](#automatic-retries); persistent failures point to a local network issue

309 

310If `curl` succeeds but Claude Code still fails, the cause is usually something between Node.js and the network rather than the network itself:

311 

312* On Linux and WSL, check `/etc/resolv.conf` for an unreachable nameserver. WSL in particular can inherit a broken resolver from the host.

313* On macOS, a VPN client that was disconnected or uninstalled can leave a tunnel interface or routing rule behind. Check `ifconfig` for stale `utun` interfaces and remove the VPN's network extension in System Settings.

314* Docker Desktop and similar container runtimes can intercept outbound traffic. Quit them and retry to rule this out.

315 

316### SSL certificate errors

317 

318A proxy or security appliance on your network is intercepting TLS traffic with its own certificate, and Node.js does not trust it.

319 

320```text theme={null}

321Unable to connect to API: SSL certificate verification failed. Check your proxy or corporate SSL certificates

322Unable to connect to API: Self-signed certificate detected

323```

324 

325**What to do:**

326 

327* Export your organization's CA bundle and point Node at it with `NODE_EXTRA_CA_CERTS=/path/to/ca-bundle.pem`

328* See [Network configuration](/en/network-config#custom-ca-certificates) for full setup instructions

329* Do not set `NODE_TLS_REJECT_UNAUTHORIZED=0`, which disables certificate validation entirely

330 

331## Request errors

332 

333These errors mean the API received your request but rejected its content.

334 

335### Prompt is too long

336 

337The conversation plus attached files exceeds the model's context window.

338 

339```text theme={null}

340Prompt is too long

341```

342 

343**What to do:**

344 

345* Run `/compact` to summarize earlier turns and free space, or `/clear` to start fresh

346* Run `/context` to see a breakdown of what is consuming the window: system prompt, tools, memory files, and messages

347* Disable MCP servers you are not using with `/mcp disable <name>` to remove their tool definitions from context

348* Trim large `CLAUDE.md` memory files, or move instructions into [path-scoped rules](/en/memory#path-specific-rules) that load only when relevant

349* Subagents inherit every MCP tool definition from the parent session, which can fill their context window before the first turn. Disable MCP servers you are not using before spawning subagents.

350* Auto-compact is on by default and normally prevents this error. If you have set [`DISABLE_AUTO_COMPACT`](/en/env-vars), re-enable it or run `/compact` manually before the window fills.

351 

352See [Explore the context window](/en/context-window) for an interactive view of how context fills up.

353 

354### Error during compaction: Conversation too long

355 

356`/compact` itself failed because there is not enough free context to hold the summary it produces.

357 

358```text theme={null}

359Error during compaction: Conversation too long. Press esc twice to go up a few messages and try again.

360```

361 

362This can happen when the window is already full at the moment auto-compact triggers, or when you run `/compact` after seeing `Prompt is too long`.

363 

364**What to do:**

365 

366* Press Esc twice to open the message list and step back several turns. This drops the most recent messages from context. Then run `/compact` again.

367* If stepping back does not free enough space, run `/clear` to start a fresh session. Your previous conversation is preserved and can be reopened with `/resume`.

368 

369### Request too large

370 

371The raw request body exceeded the API's byte limit before tokenization, usually because of a large pasted file or attachment.

372 

373```text theme={null}

374Request too large (max 30 MB). Double press esc to go back and remove or shrink the attached content.

375```

376 

377This is a size limit on the HTTP request, separate from the [context window limit](#prompt-is-too-long).

378 

379**What to do:**

380 

381* Press Esc twice and step back past the turn that added the oversized content

382* Reference large files by path instead of pasting their contents, so Claude can read them in chunks

383* For images, see [Image was too large](#image-was-too-large) below

384 

385### Image was too large

386 

387A pasted or attached image exceeds the API's size or dimension limits.

388 

389```text theme={null}

390Image was too large. Double press esc to go back and try again with a smaller image.

391API Error: 400 ... image dimensions exceed max allowed size

392```

393 

394The image stays in conversation history after the error, so every subsequent message fails with the same error until you remove it.

395 

396**What to do:**

397 

398* Press Esc twice and step back past the turn where the image was added

399* Resize the image before pasting. The API accepts images up to 8000 pixels on the longest edge for a single image, or 2000 pixels when many images are in context.

400* Take a tighter screenshot of the relevant region instead of the full screen

401 

402### PDF errors

403 

404The PDF you attached could not be processed.

405 

406```text theme={null}

407PDF too large (max 100 pages, 32 MB). Try splitting it or extracting text first.

408PDF is password protected. Try removing protection or extracting text first.

409The PDF file was not valid. Try converting to a different format first.

410```

411 

412**What to do:**

413 

414* For oversized PDFs, ask Claude to read a page range with the Read tool instead of attaching the whole file, or extract text with a tool like `pdftotext` and reference the output file by path

415* For protected or invalid PDFs, remove the password or re-export the file from its source application, then try again

416 

417### Extra inputs are not permitted

418 

419A proxy or LLM gateway between Claude Code and the API stripped the `anthropic-beta` request header, so the API rejected fields that depend on it.

420 

421```text theme={null}

422API Error: 400 ... Extra inputs are not permitted ... context_management

423API Error: 400 ... Extra inputs are not permitted ... tools.0.custom.input_examples

424API Error: 400 ... Unexpected value(s) for the `anthropic-beta` header

425```

426 

427Claude Code sends beta-only fields such as `context_management`, `effort`, and tool `input_examples` alongside an `anthropic-beta` header that enables them. When a gateway forwards the body but drops the header, the API sees fields it does not recognize.

428 

429**What to do:**

430 

431* Configure your gateway to forward the `anthropic-beta` header. See [LLM gateway configuration](/en/llm-gateway).

432* As a fallback, set [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](/en/env-vars) before launching. This disables features that require the beta header so requests succeed through a gateway that cannot forward it.

433 

434### There's an issue with the selected model

435 

436The configured model name was not recognized or your account lacks access to it.

437 

438```text theme={null}

439There's an issue with the selected model (claude-...). It may not exist or you may not have access to it. Run /model to select a different one.

440```

441 

442**What to do:**

443 

444* Run `/model` to pick from models available to your account

445* Use an alias such as `sonnet` or `opus` instead of a full versioned ID. Aliases track the latest release so they do not go stale. See [Model configuration](/en/model-config).

446* See [Model not found](/en/troubleshooting#model-not-found-or-not-accessible) to locate where a stale ID is set across `--model`, `ANTHROPIC_MODEL`, and settings files

447 

448### Claude Opus is not available with the Claude Pro plan

449 

450Your active subscription plan does not include the model you selected.

451 

452```text theme={null}

453Claude Opus is not available with the Claude Pro plan · Select a different model in /model

454```

455 

456**What to do:**

457 

458* Run `/model` and select a model your plan includes

459* If you upgraded your plan recently and still see this, run `/logout` then `/login`. The stored token reflects your plan at the time you signed in, so upgrading on the web does not take effect in an existing session until you re-authenticate.

460* See [claude.com/pricing](https://claude.com/pricing) for which models each plan includes

461 

462### thinking.type.enabled is not supported for this model

463 

464Your Claude Code version is older than the minimum for Opus 4.7. The CLI sent a thinking configuration the model no longer accepts.

465 

466```text theme={null}

467API Error: 400 ... "thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.

468```

469 

470**What to do:**

471 

472* Run `claude update` to upgrade to v2.1.111 or later, then restart Claude Code

473* If you cannot upgrade, run `/model` and select Opus 4.6 or Sonnet instead

474* If you hit this in the Agent SDK, see [SDK troubleshooting](/en/agent-sdk/quickstart#troubleshooting)

475 

476### Thinking budget exceeds output limit

477 

478The configured extended thinking budget exceeds the maximum response length, so there is no room left for the actual answer.

479 

480```text theme={null}

481API Error: 400 ... max_tokens must be greater than thinking.budget_tokens

482```

483 

484Claude Code adjusts these values automatically on the Anthropic API. You typically see this error on Amazon Bedrock or Google Vertex AI when [`MAX_THINKING_TOKENS`](/en/env-vars) is set higher than the provider's output limit, or when plan mode raises the thinking budget.

485 

486**What to do:**

487 

488* Lower `MAX_THINKING_TOKENS`, or raise [`CLAUDE_CODE_MAX_OUTPUT_TOKENS`](/en/env-vars) above the thinking budget

489* See [Extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) for how the budget interacts with output length

490 

491### Tool use or thinking block mismatch

492 

493The conversation history reached the API in an inconsistent state, usually after a tool call was interrupted or a turn was edited mid-stream.

494 

495```text theme={null}

496API Error: 400 due to tool use concurrency issues. Run /rewind to recover the conversation.

497API Error: 400 ... unexpected `tool_use_id` found in `tool_result` blocks

498API Error: 400 ... thinking blocks ... cannot be modified

499```

500 

501All three variants mean the same thing: the sequence of `tool_use`, `tool_result`, and `thinking` blocks in history no longer matches what the API expects.

502 

503**What to do:**

504 

505* Run `/rewind`, or press Esc twice, to step back to a checkpoint before the corrupted turn and continue from there. See [Checkpointing](/en/checkpointing) for how checkpoints are created and restored.

506 

507## Responses seem lower quality than usual

508 

509If Claude's answers seem less capable than you expect but no error is shown, the cause is usually conversation state rather than the model itself. Claude Code does not silently change model versions. It can switch to a fallback model in specific cases such as an Opus quota being reached or a Bedrock or Vertex AI region lacking your model; the Model selection check below catches both, and [Model configuration](/en/model-config) explains when fallback applies.

510 

511Check these first:

512 

513* **Model selection**: run `/model` to confirm you are on the model you expect. A previous `/model` choice or an `ANTHROPIC_MODEL` environment variable may have you on a smaller model than you intended.

514* **Effort level**: run `/effort` to check the current reasoning level and raise it for hard debugging or design work. Defaults vary by model, so check before assuming you are below the maximum. See [Adjust effort level](/en/model-config#adjust-effort-level) for per-model defaults and the `ultrathink` shortcut.

515* **Context pressure**: run `/context` to see how full the window is. If it is near capacity, run `/compact` at a natural breakpoint or `/clear` to start fresh. See [Explore the context window](/en/context-window) for how auto-compact affects earlier turns.

516* **Stale instructions**: large or outdated `CLAUDE.md` files and MCP tool definitions consume context and can steer responses. `/doctor` flags oversized memory files and subagent definitions; `/context` shows MCP tool token usage.

517 

518When a response goes wrong, rewinding usually works better than replying with corrections. Press Esc twice or run `/rewind` to step back to before the bad turn, then rephrase the prompt with more specifics. Correcting in-thread keeps the wrong attempt in context, which can anchor later answers to it. See [Checkpointing](/en/checkpointing).

519 

520If quality still seems off after checking the above, run `/feedback` and describe what you expected versus what you got. Feedback submitted this way includes the conversation transcript, which is the fastest way for Anthropic to diagnose a real regression. See [Report an error](#report-an-error) if `/feedback` is unavailable on your provider.

521 

522## Report an error

523 

524This page covers errors from the Claude API. For errors from other Claude Code components, see the relevant guide:

525 

526* MCP server failed to connect or authenticate: [MCP](/en/mcp)

527* Hook script failed or blocked a tool: [Debug hooks](/en/hooks#debug-hooks)

528* Permission denied or filesystem errors during install: [Troubleshooting](/en/troubleshooting)

529 

530If an error is not listed here or the suggested fix does not help:

531 

532* Run `/feedback` inside Claude Code to send the transcript and a description to Anthropic. The command also offers to open a prefilled GitHub issue. Feedback is unavailable on Bedrock, Vertex AI, and Foundry deployments.

533* Run `/doctor` to check for local configuration problems

534* Check [status.claude.com](https://status.claude.com) for active incidents

535* Search [existing issues](https://github.com/anthropics/claude-code/issues) on GitHub

fast-mode.md +150 −0 added

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# Speed up responses with fast mode

6 

7> Get faster Opus 4.6 responses in Claude Code by toggling fast mode.

8 

9<Note>

10 Fast mode is in [research preview](#research-preview). The feature, pricing, and availability may change based on feedback.

11</Note>

12 

13Fast mode is a high-speed configuration for Claude Opus 4.6, making the model 2.5x faster at a higher cost per token. Toggle it on with `/fast` when you need speed for interactive work like rapid iteration or live debugging, and toggle it off when cost matters more than latency.

14 

15Fast mode is not a different model. It uses the same Opus 4.6 with a different API configuration that prioritizes speed over cost efficiency. You get identical quality and capabilities, just faster responses. Fast mode is not available on Opus 4.7 or other models.

16 

17<Note>

18 Fast mode requires Claude Code v2.1.36 or later. Check your version with `claude --version`.

19</Note>

20 

21What to know:

22 

23* Use `/fast` to toggle on fast mode in Claude Code CLI. Also available via `/fast` in Claude Code VS Code Extension.

24* Fast mode for Opus 4.6 pricing is \$30/150 MTok.

25* Available to all Claude Code users on subscription plans (Pro/Max/Team/Enterprise) and Claude Console.

26* For Claude Code users on subscription plans (Pro/Max/Team/Enterprise), fast mode is available via extra usage only and not included in the subscription rate limits.

27 

28This page covers how to [toggle fast mode](#toggle-fast-mode), its [cost tradeoff](#understand-the-cost-tradeoff), [when to use it](#decide-when-to-use-fast-mode), [requirements](#requirements), [per-session opt-in](#require-per-session-opt-in), and [rate limit behavior](#handle-rate-limits).

29 

30## Toggle fast mode

31 

32Toggle fast mode in either of these ways:

33 

34* Type `/fast` and press Tab to toggle on or off

35* Set `"fastMode": true` in your [user settings file](/en/settings)

36 

37By default, fast mode persists across sessions. Administrators can configure fast mode to reset each session. See [require per-session opt-in](#require-per-session-opt-in) for details.

38 

39For the best cost efficiency, enable fast mode at the start of a session rather than switching mid-conversation. See [understand the cost tradeoff](#understand-the-cost-tradeoff) for details.

40 

41When you enable fast mode:

42 

43* If you're on a different model, Claude Code automatically switches to Opus 4.6

44* You'll see a confirmation message: "Fast mode ON"

45* A small `↯` icon appears next to the prompt while fast mode is active

46* Run `/fast` again at any time to check whether fast mode is on or off

47 

48When you disable fast mode with `/fast` again, you remain on Opus 4.6. The model does not revert to your previous model. To switch to a different model, use `/model`.

49 

50## Understand the cost tradeoff

51 

52Fast mode has higher per-token pricing than standard Opus 4.6:

53 

54| Mode | Input (MTok) | Output (MTok) |

55| --------------------- | ------------ | ------------- |

56| Fast mode on Opus 4.6 | \$30 | \$150 |

57 

58Fast mode pricing is flat across the full 1M token context window.

59 

60When you switch into fast mode mid-conversation, you pay the full fast mode uncached input token price for the entire conversation context. This costs more than if you had enabled fast mode from the start.

61 

62## Decide when to use fast mode

63 

64Fast mode is best for interactive work where response latency matters more than cost:

65 

66* Rapid iteration on code changes

67* Live debugging sessions

68* Time-sensitive work with tight deadlines

69 

70Standard mode is better for:

71 

72* Long autonomous tasks where speed matters less

73* Batch processing or CI/CD pipelines

74* Cost-sensitive workloads

75 

76### Fast mode vs effort level

77 

78Fast mode and effort level both affect response speed, but differently:

79 

80| Setting | Effect |

81| ---------------------- | -------------------------------------------------------------------------------- |

82| **Fast mode** | Same model quality, lower latency, higher cost |

83| **Lower effort level** | Less thinking time, faster responses, potentially lower quality on complex tasks |

84 

85You can combine both: use fast mode with a lower [effort level](/en/model-config#adjust-effort-level) for maximum speed on straightforward tasks.

86 

87## Requirements

88 

89Fast mode requires all of the following:

90 

91* **Not available on third-party cloud providers**: fast mode is not available on Amazon Bedrock, Google Vertex AI, or Microsoft Azure Foundry. Fast mode is available through the Anthropic Console API and for Claude subscription plans using extra usage.

92* **Extra usage enabled**: your account must have extra usage enabled, which allows billing beyond your plan's included usage. For individual accounts, enable this in your [Console billing settings](https://platform.claude.com/settings/organization/billing). For Team and Enterprise, an admin must enable extra usage for the organization.

93 

94<Note>

95 Fast mode usage is billed directly to extra usage, even if you have remaining usage on your plan. This means fast mode tokens do not count against your plan's included usage and are charged at the fast mode rate from the first token.

96</Note>

97 

98* **Admin enablement for Team and Enterprise**: fast mode is disabled by default for Team and Enterprise organizations. An admin must explicitly [enable fast mode](#enable-fast-mode-for-your-organization) before users can access it.

99 

100<Note>

101 If your admin has not enabled fast mode for your organization, the `/fast` command will show "Fast mode has been disabled by your organization."

102</Note>

103 

104### Enable fast mode for your organization

105 

106Admins can enable fast mode in:

107 

108* **Console** (API customers): [Claude Code preferences](https://platform.claude.com/claude-code/preferences)

109* **Claude AI** (Team and Enterprise): [Admin Settings > Claude Code](https://claude.ai/admin-settings/claude-code)

110 

111Another option to disable fast mode entirely is to set `CLAUDE_CODE_DISABLE_FAST_MODE=1`. See [Environment variables](/en/env-vars).

112 

113### Require per-session opt-in

114 

115By default, fast mode persists across sessions: if a user enables fast mode, it stays on in future sessions. Administrators on [Team](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=fast_mode_teams#team-&-enterprise) or [Enterprise](https://anthropic.com/contact-sales?utm_source=claude_code\&utm_medium=docs\&utm_content=fast_mode_enterprise) plans can prevent this by setting `fastModePerSessionOptIn` to `true` in [managed settings](/en/settings#settings-files) or [server-managed settings](/en/server-managed-settings). This causes each session to start with fast mode off, requiring users to explicitly enable it with `/fast`.

116 

117```json theme={null}

118{

119 "fastModePerSessionOptIn": true

120}

121```

122 

123This is useful for controlling costs in organizations where users run multiple concurrent sessions. Users can still enable fast mode with `/fast` when they need speed, but it resets at the start of each new session. The user's fast mode preference is still saved, so removing this setting restores the default persistent behavior.

124 

125## Handle rate limits

126 

127Fast mode has separate rate limits from standard Opus 4.6. When you hit the fast mode rate limit or run out of extra usage:

128 

1291. Fast mode automatically falls back to standard Opus 4.6

1302. The `↯` icon turns gray to indicate cooldown

1313. You continue working at standard speed and pricing

1324. When the cooldown expires, fast mode automatically re-enables

133 

134To disable fast mode manually instead of waiting for cooldown, run `/fast` again.

135 

136## Research preview

137 

138Fast mode is a research preview feature. This means:

139 

140* The feature may change based on feedback

141* Availability and pricing are subject to change

142* The underlying API configuration may evolve

143 

144Report issues or feedback through your usual Anthropic support channels.

145 

146## See also

147 

148* [Model configuration](/en/model-config): switch models and adjust effort levels

149* [Manage costs effectively](/en/costs): track token usage and reduce costs

150* [Status line configuration](/en/statusline): display model and context information

Details

12 For how the core agentic loop works, see [How Claude Code works](/en/how-claude-code-works).12 For how the core agentic loop works, see [How Claude Code works](/en/how-claude-code-works).

13</Note>13</Note>

14 14 

15**New to Claude Code?** Start with [CLAUDE.md](/en/memory) for project conventions. Add other extensions as you need them.15**New to Claude Code?** Start with [CLAUDE.md](/en/memory) for project conventions, then add other extensions [as specific triggers come up](#build-your-setup-over-time).

16 16 

17## Overview17## Overview

18 18 


22* **[Skills](/en/skills)** add reusable knowledge and invocable workflows22* **[Skills](/en/skills)** add reusable knowledge and invocable workflows

23* **[MCP](/en/mcp)** connects Claude to external services and tools23* **[MCP](/en/mcp)** connects Claude to external services and tools

24* **[Subagents](/en/sub-agents)** run their own loops in isolated context, returning summaries24* **[Subagents](/en/sub-agents)** run their own loops in isolated context, returning summaries

25* **[Hooks](/en/hooks)** run outside the loop entirely as deterministic scripts25* **[Agent teams](/en/agent-teams)** coordinate multiple independent sessions with shared tasks and peer-to-peer messaging

26* **[Hooks](/en/hooks-guide)** fire on lifecycle events and can run a script, HTTP request, prompt, or subagent

26* **[Plugins](/en/plugins)** and **[marketplaces](/en/plugin-marketplaces)** package and distribute these features27* **[Plugins](/en/plugins)** and **[marketplaces](/en/plugin-marketplaces)** package and distribute these features

27 28 

28[Skills](/en/skills) are the most flexible extension. A skill is a markdown file containing knowledge, workflows, or instructions. You can invoke skills with a slash command like `/deploy`, or Claude can load them automatically when relevant. Skills can run in your current conversation or in an isolated context via subagents.29[Skills](/en/skills) are the most flexible extension. A skill is a markdown file containing knowledge, workflows, or instructions. You can invoke skills with a command like `/deploy`, or Claude can load them automatically when relevant. Skills can run in your current conversation or in an isolated context via subagents.

29 30 

30## Match features to your goal31## Match features to your goal

31 32 

32Features range from always-on context that Claude sees every session, to on-demand capabilities you or Claude can invoke, to background automation that runs on specific events. The table below shows what's available and when each one makes sense.33Features range from always-on context that Claude sees every session, to on-demand capabilities you or Claude can invoke, to background automation that runs on specific events. The table below shows what's available and when each one makes sense.

33 34 

34| Feature | What it does | When to use it | Example |35| Feature | What it does | When to use it | Example |

35| ------------- | ---------------------------------------------------------- | ------------------------------------------------------ | -------------------------------------------------------------------------------- |36| ---------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |

36| **CLAUDE.md** | Persistent context loaded every conversation | Project conventions, "always do X" rules | "Use pnpm, not npm. Run tests before committing." |37| **CLAUDE.md** | Persistent context loaded every conversation | Project conventions, "always do X" rules | "Use pnpm, not npm. Run tests before committing." |

37| **Skill** | Instructions, knowledge, and workflows Claude can use | Reusable content, reference docs, repeatable tasks | `/review` runs your code review checklist; API docs skill with endpoint patterns |38| **Skill** | Instructions, knowledge, and workflows Claude can use | Reusable content, reference docs, repeatable tasks | `/deploy` runs your deployment checklist; API docs skill with endpoint patterns |

38| **Subagent** | Isolated execution context that returns summarized results | Context isolation, parallel tasks, specialized workers | Research task that reads many files but returns only key findings |39| **Subagent** | Isolated execution context that returns summarized results | Context isolation, parallel tasks, specialized workers | Research task that reads many files but returns only key findings |

40| **[Agent teams](/en/agent-teams)** | Coordinate multiple independent Claude Code sessions | Parallel research, new feature development, debugging with competing hypotheses | Spawn reviewers to check security, performance, and tests simultaneously |

39| **MCP** | Connect to external services | External data or actions | Query your database, post to Slack, control a browser |41| **MCP** | Connect to external services | External data or actions | Query your database, post to Slack, control a browser |

40| **Hook** | Deterministic script that runs on events | Predictable automation, no LLM involved | Run ESLint after every file edit |42| **Hook** | Script, HTTP request, prompt, or subagent triggered by events | Automation that must run on every matching event | Run ESLint after every file edit |

41 43 

42**[Plugins](/en/plugins)** are the packaging layer. A plugin bundles skills, hooks, subagents, and MCP servers into a single installable unit. Plugin skills are namespaced (like `/my-plugin:review`) so multiple plugins can coexist. Use plugins when you want to reuse the same setup across multiple repositories or distribute to others via a **[marketplace](/en/plugin-marketplaces)**.44**[Plugins](/en/plugins)** are the packaging layer. A plugin bundles skills, hooks, subagents, and MCP servers into a single installable unit. Plugin skills are namespaced (like `/my-plugin:review`) so multiple plugins can coexist. Use plugins when you want to reuse the same setup across multiple repositories or distribute to others via a **[marketplace](/en/plugin-marketplaces)**.

43 45 

46### Build your setup over time

47 

48You don't need to configure everything up front. Each feature has a recognizable trigger, and most teams add them in roughly this order:

49 

50| Trigger | Add |

51| :------------------------------------------------------------------------------- | :---------------------------------------------- |

52| Claude gets a convention or command wrong twice | Add it to [CLAUDE.md](/en/memory) |

53| You keep typing the same prompt to start a task | Save it as a user-invocable [skill](/en/skills) |

54| You paste the same playbook or multi-step procedure into chat for the third time | Capture it as a [skill](/en/skills) |

55| You keep copying data from a browser tab Claude can't see | Connect that system as an [MCP server](/en/mcp) |

56| A side task floods your conversation with output you won't reference again | Route it through a [subagent](/en/sub-agents) |

57| You want something to happen every time without asking | Write a [hook](/en/hooks-guide) |

58| A second repository needs the same setup | Package it as a [plugin](/en/plugins) |

59 

60The same triggers tell you when to update what you already have. A repeated mistake or a recurring review comment is a CLAUDE.md edit, not a one-off correction in chat. A workflow you keep tweaking by hand is a skill that needs another revision.

61 

44### Compare similar features62### Compare similar features

45 63 

46Some features can seem similar. Here's how to tell them apart.64Some features can seem similar. Here's how to tell them apart.


79 97 

80 **Put it in a skill** if it's reference material Claude needs sometimes (API docs, style guides) or a workflow you trigger with `/<name>` (deploy, review, release).98 **Put it in a skill** if it's reference material Claude needs sometimes (API docs, style guides) or a workflow you trigger with `/<name>` (deploy, review, release).

81 99 

82 **Rule of thumb:** Keep CLAUDE.md under \~500 lines. If it's growing, move reference content to skills.100 **Rule of thumb:** Keep CLAUDE.md under 200 lines. If it's growing, move reference content to skills or split into [`.claude/rules/`](/en/memory#organize-rules-with-claude/rules/) files.

101 </Tab>

102 

103 <Tab title="CLAUDE.md vs Rules vs Skills">

104 All three store instructions, but they load differently:

105 

106 | Aspect | CLAUDE.md | `.claude/rules/` | Skill |

107 | ------------ | ----------------------------------- | -------------------------------------------------- | ---------------------------------------- |

108 | **Loads** | Every session | Every session, or when matching files are opened | On demand, when invoked or relevant |

109 | **Scope** | Whole project | Can be scoped to file paths | Task-specific |

110 | **Best for** | Core conventions and build commands | Language-specific or directory-specific guidelines | Reference material, repeatable workflows |

111 

112 **Use CLAUDE.md** for instructions every session needs: build commands, test conventions, project architecture.

113 

114 **Use rules** to keep CLAUDE.md focused. Rules with [`paths` frontmatter](/en/memory#path-specific-rules) only load when Claude works with matching files, saving context.

115 

116 **Use skills** for content Claude only needs sometimes, like API documentation or a deployment checklist you trigger with `/<name>`.

117 </Tab>

118 

119 <Tab title="Subagent vs Agent team">

120 Both parallelize work, but they're architecturally different:

121 

122 * **Subagents** run inside your session and report results back to your main context

123 * **Agent teams** are independent Claude Code sessions that communicate with each other

124 

125 | Aspect | Subagent | Agent team |

126 | ----------------- | ------------------------------------------------ | --------------------------------------------------- |

127 | **Context** | Own context window; results return to the caller | Own context window; fully independent |

128 | **Communication** | Reports results back to the main agent only | Teammates message each other directly |

129 | **Coordination** | Main agent manages all work | Shared task list with self-coordination |

130 | **Best for** | Focused tasks where only the result matters | Complex work requiring discussion and collaboration |

131 | **Token cost** | Lower: results summarized back to main context | Higher: each teammate is a separate Claude instance |

132 

133 **Use a subagent** when you need a quick, focused worker: research a question, verify a claim, review a file. The subagent does the work and returns a summary. Your main conversation stays clean.

134 

135 **Use an agent team** when teammates need to share findings, challenge each other, and coordinate independently. Agent teams are best for research with competing hypotheses, parallel code review, and new feature development where each teammate owns a separate piece.

136 

137 **Transition point:** If you're running parallel subagents but hitting context limits, or if your subagents need to communicate with each other, agent teams are the natural next step.

138 

139 <Note>

140 Agent teams are experimental and disabled by default. See [agent teams](/en/agent-teams) for setup and current limitations.

141 </Note>

83 </Tab>142 </Tab>

84 143 

85 <Tab title="MCP vs Skill">144 <Tab title="MCP vs Skill">


99 158 

100 Example: An MCP server connects Claude to your database. A skill teaches Claude your data model, common query patterns, and which tables to use for different tasks.159 Example: An MCP server connects Claude to your database. A skill teaches Claude your data model, common query patterns, and which tables to use for different tasks.

101 </Tab>160 </Tab>

161 

162 <Tab title="Hook vs Skill">

163 A hook fires on a lifecycle event; a skill is loaded into context for Claude to apply.

164 

165 | Aspect | Hook | Skill |

166 | ---------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------- |

167 | **Runs** | A shell command, HTTP request, LLM prompt, or subagent | Instructions Claude reads and follows |

168 | **Triggered by** | [Lifecycle events](/en/hooks#hook-events) such as `PostToolUse` or `SessionStart` | You typing `/<name>`, or Claude matching the description to your task |

169 | **Determinism** | Always fires on its event; the trigger is guaranteed | Claude interprets the instructions; outcome can vary |

170 | **Context cost** | Zero unless the hook returns output | Description loads each session; full content loads when used |

171 | **Best for** | Linting after edits, blocking unsafe commands, logging, notifications | Workflows that need reasoning, reference material, multi-step tasks |

172 

173 **Use a hook** when the action must happen the same way every time and doesn't need Claude to think. For example: format on save, reject `rm -rf /`, post a Slack message when a session ends.

174 

175 **Use a skill** when Claude should decide how to apply the steps, or when the content is knowledge rather than a script. For example: a `/release` checklist, your API style guide, a debugging playbook.

176 

177 **Put guardrails in hooks.** An instruction like "never edit `.env`" in CLAUDE.md or a skill is a request, not a guarantee. A `PreToolUse` hook that blocks the edit is enforcement. If a rule must hold every time, make it a hook rather than a prompt instruction.

178 

179 **Hook output lands in context.** A `PostToolUse` hook that runs your linter feeds results back as text Claude reads; a `/fix-lint` skill tells Claude how to resolve them.

180 </Tab>

102</Tabs>181</Tabs>

103 182 

104### Understand how features layer183### Understand how features layer

105 184 

106Features 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:185Features 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:

107 186 

108* **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 looks up memories](/en/memory#how-claude-looks-up-memories).187* **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).

109* **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).188* **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).

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

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


117For example, you might use CLAUDE.md for project conventions, a skill for your deployment workflow, MCP to connect to your database, and a hook to run linting after every edit. Each feature handles what it's best at.196For example, you might use CLAUDE.md for project conventions, a skill for your deployment workflow, MCP to connect to your database, and a hook to run linting after every edit. Each feature handles what it's best at.

118 197 

119| Pattern | How it works | Example |198| Pattern | How it works | Example |

120| ---------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |199| ---------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |

121| **Skill + MCP** | MCP provides the connection; a skill teaches Claude how to use it well | MCP connects to your database, a skill documents your schema and query patterns |200| **Skill + MCP** | MCP provides the connection; a skill teaches Claude how to use it well | MCP connects to your database, a skill documents your schema and query patterns |

122| **Skill + Subagent** | A skill spawns subagents for parallel work | `/review` skill kicks off security, performance, and style subagents that work in isolated context |201| **Skill + Subagent** | A skill spawns subagents for parallel work | `/audit` skill kicks off security, performance, and style subagents that work in isolated context |

123| **CLAUDE.md + Skills** | CLAUDE.md holds always-on rules; skills hold reference material loaded on demand | CLAUDE.md says "follow our API conventions," a skill contains the full API style guide |202| **CLAUDE.md + Skills** | CLAUDE.md holds always-on rules; skills hold reference material loaded on demand | CLAUDE.md says "follow our API conventions," a skill contains the full API style guide |

124| **Hook + MCP** | A hook triggers external actions through MCP | Post-edit hook sends a Slack notification when Claude modifies critical files |203| **Hook + MCP** | A hook triggers external actions through MCP | Post-edit hook sends a Slack notification when Claude modifies critical files |

125 204 

126## Understand context costs205## Understand context costs

127 206 

128Every feature you add consumes some of Claude's context. Too much can fill up your context window, but it can also add noise that makes Claude less effective; skills may not trigger correctly, or Claude may lose track of your conventions. Understanding these trade-offs helps you build an effective setup.207Every feature you add consumes some of Claude's context. Too much can fill up your context window, but it can also add noise that makes Claude less effective; skills may not trigger correctly, or Claude may lose track of your conventions. Understanding these trade-offs helps you build an effective setup. For an interactive view of how these features combine in a running session, see [Explore the context window](/en/context-window).

129 208 

130### Context cost by feature209### Context cost by feature

131 210 


135| --------------- | ------------------------- | --------------------------------------------- | -------------------------------------------- |214| --------------- | ------------------------- | --------------------------------------------- | -------------------------------------------- |

136| **CLAUDE.md** | Session start | Full content | Every request |215| **CLAUDE.md** | Session start | Full content | Every request |

137| **Skills** | Session start + when used | Descriptions at start, full content when used | Low (descriptions every request)\* |216| **Skills** | Session start + when used | Descriptions at start, full content when used | Low (descriptions every request)\* |

138| **MCP servers** | Session start | All tool definitions and schemas | Every request |217| **MCP servers** | Session start | Tool names; full schemas on demand | Low until a tool is used |

139| **Subagents** | When spawned | Fresh context with specified skills | Isolated from main session |218| **Subagents** | When spawned | Fresh context with specified skills | Isolated from main session |

140| **Hooks** | On trigger | Nothing (runs externally) | Zero, unless hook returns additional context |219| **Hooks** | On trigger | Nothing (runs externally) | Zero, unless hook returns additional context |

141 220 


145 224 

146Each feature loads at different points in your session. The tabs below explain when each one loads and what goes into context.225Each feature loads at different points in your session. The tabs below explain when each one loads and what goes into context.

147 226 

148<img src="https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/context-loading.svg?fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=bd2e24b8e6a99b31ecfffb63f5b23bf5" alt="Context loading: CLAUDE.md and MCP load at session start and stay in every request. Skills load descriptions at start, full content on invocation. Subagents get isolated context. Hooks run externally." data-og-width="720" width="720" data-og-height="410" height="410" data-path="images/context-loading.svg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/context-loading.svg?w=280&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=aebaadd1f484f285dd9cb4e0ea6d49b9 280w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/context-loading.svg?w=560&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=030c9b46126d750de315612560082727 560w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/context-loading.svg?w=840&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=6c73f8b0389da4f3190843140c810fe9 840w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/context-loading.svg?w=1100&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=9844c55d08d2c386672447f2e8518669 1100w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/context-loading.svg?w=1650&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=21a9522d0e4bd10ced146aab850ede76 1650w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/context-loading.svg?w=2500&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=d318525915aee1a1a6a4215cfaa61fb9 2500w" />227<img src="https://mintcdn.com/claude-code/6yTCYq1p37ZB8-CQ/images/context-loading.svg?fit=max&auto=format&n=6yTCYq1p37ZB8-CQ&q=85&s=5a58ce953a35a2412892015e2ad6cb67" alt="Context loading: CLAUDE.md loads at session start and stays in every request. MCP tool names load at start with full schemas deferred until use. Skills load descriptions at start, full content on invocation. Subagents get isolated context. Hooks run externally." width="720" height="410" data-path="images/context-loading.svg" />

149 228 

150<Tabs>229<Tabs>

151 <Tab title="CLAUDE.md">230 <Tab title="CLAUDE.md">


153 232 

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

155 234 

156 **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 looks up memories](/en/memory#how-claude-looks-up-memories) for details.235 **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.

157 236 

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

159 </Tab>238 </Tab>

160 239 

161 <Tab title="Skills">240 <Tab title="Skills">

162 Skills are extra capabilities in Claude's toolkit. They can be reference material (like an API style guide) or invocable workflows you trigger with `/<name>` (like `/deploy`). Some are built-in; you can also create your own. Claude uses skills when appropriate, or you can invoke one directly.241 Skills are extra capabilities in Claude's toolkit. They can be reference material (like an API style guide) or invocable workflows you trigger with `/<name>` (like `/deploy`). Claude Code includes [bundled skills](/en/commands) like `/simplify`, `/batch`, and `/debug` that work out of the box. You can also create your own. Claude uses skills when appropriate, or you can invoke one directly.

163 242 

164 **When:** Depends on the skill's configuration. By default, descriptions load at session start and full content loads when used. For user-only skills (`disable-model-invocation: true`), nothing loads until you invoke them.243 **When:** Depends on the skill's configuration. By default, descriptions load at session start and full content loads when used. For user-only skills (`disable-model-invocation: true`), nothing loads until you invoke them.

165 244 


177 <Tab title="MCP servers">256 <Tab title="MCP servers">

178 **When:** Session start.257 **When:** Session start.

179 258 

180 **What loads:** All tool definitions and JSON schemas from connected servers.259 **What loads:** Tool names from connected servers. Full JSON schemas stay deferred until Claude needs a specific tool.

181 260 

182 **Context cost:** [Tool search](/en/mcp#scale-with-mcp-tool-search) (enabled by default) loads MCP tools up to 10% of context and defers the rest until needed.261 **Context cost:** [Tool search](/en/mcp#scale-with-mcp-tool-search) is on by default, so idle MCP tools consume minimal context.

183 262 

184 **Reliability note:** MCP connections can fail silently mid-session. If a server disconnects, its tools disappear without warning. Claude may try to use a tool that no longer exists. If you notice Claude failing to use an MCP tool it previously could access, check the connection with `/mcp`.263 **Reliability note:** MCP connections can fail silently mid-session. If a server disconnects, its tools disappear without warning. Claude may try to use a tool that no longer exists. If you notice Claude failing to use an MCP tool it previously could access, check the connection with `/mcp`.

185 264 


204 <Tab title="Hooks">283 <Tab title="Hooks">

205 **When:** On trigger. Hooks fire at specific lifecycle events like tool execution, session boundaries, prompt submission, permission requests, and compaction. See [Hooks](/en/hooks) for the full list.284 **When:** On trigger. Hooks fire at specific lifecycle events like tool execution, session boundaries, prompt submission, permission requests, and compaction. See [Hooks](/en/hooks) for the full list.

206 285 

207 **What loads:** Nothing by default. Hooks run as external scripts.286 **What loads:** Nothing by default. Hooks execute outside the main conversation.

208 287 

209 **Context cost:** Zero, unless the hook returns output that gets added as messages to your conversation.288 **Context cost:** Zero, unless the hook returns output that gets added as messages to your conversation.

210 289 


229 Offload work to isolated context308 Offload work to isolated context

230 </Card>309 </Card>

231 310 

311 <Card title="Agent teams" icon="network" href="/en/agent-teams">

312 Coordinate multiple sessions working in parallel

313 </Card>

314 

232 <Card title="MCP" icon="plug" href="/en/mcp">315 <Card title="MCP" icon="plug" href="/en/mcp">

233 Connect Claude to external services316 Connect Claude to external services

234 </Card>317 </Card>

fullscreen.md +153 −0 added

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# Fullscreen rendering

6 

7> Enable a smoother, flicker-free rendering mode with mouse support and stable memory usage in long conversations.

8 

9<Note>

10 Fullscreen rendering is an opt-in [research preview](#research-preview) and requires Claude Code v2.1.89 or later. Run `/tui fullscreen` to switch in your current conversation, or set `CLAUDE_CODE_NO_FLICKER=1` on versions before v2.1.110. Behavior may change based on feedback.

11</Note>

12 

13Fullscreen rendering is an alternative rendering path for the Claude Code CLI that eliminates flicker, keeps memory usage flat in long conversations, and adds mouse support. It draws the interface on the terminal's alternate screen buffer, like `vim` or `htop`, and only renders messages that are currently visible. This reduces the amount of data sent to your terminal on each update.

14 

15The difference is most noticeable in terminal emulators where rendering throughput is the bottleneck, such as the VS Code integrated terminal, tmux, and iTerm2. If your terminal scroll position jumps to the top while Claude is working, or the screen flashes as tool output streams in, this mode addresses those.

16 

17<Note>

18 The term fullscreen describes how Claude Code takes over the terminal's drawing surface, the way `vim` does. It has nothing to do with maximizing your terminal window, and works at any window size.

19</Note>

20 

21## Enable fullscreen rendering

22 

23Run `/tui fullscreen` inside any Claude Code conversation. The CLI saves the [`tui` setting](/en/settings#available-settings) and relaunches into fullscreen with your conversation intact, so you can switch mid-session without losing context. Run `/tui` with no argument to print which renderer is active.

24 

25You can also set the `CLAUDE_CODE_NO_FLICKER` environment variable before starting Claude Code:

26 

27```bash theme={null}

28CLAUDE_CODE_NO_FLICKER=1 claude

29```

30 

31The `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.

32 

33## What changes

34 

35Fullscreen rendering changes how the CLI draws to your terminal. The input box stays fixed at the bottom of the screen instead of moving as output streams in. If the input stays put while Claude is working, fullscreen rendering is active. Only visible messages are kept in the render tree, so memory stays constant regardless of conversation length.

36 

37Because the conversation lives in the alternate screen buffer instead of your terminal's scrollback, a few things work differently:

38 

39| Before | Now | Details |

40| :-------------------------------------------------- | :----------------------------------------------------------------------------- | :------------------------------------------------------------------------ |

41| `Cmd+f` or tmux search to find text | `Ctrl+o` for transcript mode, then `/` to search or `[` to write to scrollback | [Search and review the conversation](#search-and-review-the-conversation) |

42| Terminal's native click-and-drag to select and copy | In-app selection, copies automatically on mouse release | [Use the mouse](#use-the-mouse) |

43| `Cmd`-click to open a URL | Click the URL | [Use the mouse](#use-the-mouse) |

44 

45If mouse capture interferes with your workflow, you can [turn it off](#keep-native-text-selection) while keeping the flicker-free rendering.

46 

47## Use the mouse

48 

49Fullscreen rendering captures mouse events and handles them inside Claude Code:

50 

51* **Click in the prompt input** to position your cursor anywhere in the text you're typing.

52* **Click a collapsed tool result** to expand it and see the full output. Click again to collapse. The tool call and its result expand together. Only messages that have more to show are clickable.

53* **Click a URL or file path** to open it. File paths in tool output, like the ones printed after an Edit or Write, open in your default application. Plain `http://` and `https://` URLs open in your browser. In most terminals this replaces native `Cmd`-click or `Ctrl`-click, which mouse capture intercepts. In the VS Code integrated terminal and similar xterm.js-based terminals, keep using `Cmd`-click. Claude Code defers to the terminal's own link handler there to avoid opening links twice.

54* **Click and drag** to select text anywhere in the conversation. Double-click selects a word, matching iTerm2's word boundaries so a file path selects as one unit. Triple-click selects the line.

55* **Scroll with the mouse wheel** to move through the conversation.

56 

57Selected text copies to your clipboard automatically on mouse release. To turn this off, toggle Copy on select in `/config`. With it off, press `Ctrl+Shift+c` to copy manually. On terminals that support the kitty keyboard protocol, such as kitty, WezTerm, Ghostty, and iTerm2, `Cmd+c` also works. If you have a selection active, `Ctrl+c` copies instead of cancelling.

58 

59With a selection active, hold `Shift` and press the arrow keys to extend it from the keyboard. `Shift+↑` and `Shift+↓` scroll the viewport when the selection reaches the top or bottom edge. `Shift+Home` and `Shift+End` extend to the start or end of the current line.

60 

61## Scroll the conversation

62 

63Fullscreen rendering handles scrolling inside the app. Use these shortcuts to navigate:

64 

65| Shortcut | Action |

66| :-------------- | :--------------------------------------------------- |

67| `PgUp` / `PgDn` | Scroll up or down by half a screen |

68| `Ctrl+Home` | Jump to the start of the conversation |

69| `Ctrl+End` | Jump to the latest message and re-enable auto-follow |

70| Mouse wheel | Scroll a few lines at a time |

71 

72On keyboards without dedicated `PgUp`, `PgDn`, `Home`, or `End` keys, like MacBook keyboards, hold `Fn` with the arrow keys: `Fn+↑` sends `PgUp`, `Fn+↓` sends `PgDn`, `Fn+←` sends `Home`, and `Fn+→` sends `End`. That makes `Ctrl+Fn+→` the jump-to-bottom shortcut. If that feels awkward, scroll to the bottom with the mouse wheel to resume following, or rebind `scroll:bottom` to something reachable.

73 

74These actions are rebindable. See [Scroll actions](/en/keybindings#scroll-actions) for the full list of action names, including half-page and full-page variants that have no default binding.

75 

76### Auto-follow

77 

78Scrolling up pauses auto-follow so new output does not pull you back to the bottom. Press `Ctrl+End` or scroll to the bottom to resume following.

79 

80To turn auto-follow off entirely so the view stays where you leave it, open `/config` and set Auto-scroll to off. With auto-scroll disabled, the view never jumps to the bottom on its own. Permission prompts and other dialogs that need a response still scroll into view regardless of this setting.

81 

82### Mouse wheel scrolling

83 

84Mouse wheel scrolling requires your terminal to forward mouse events to Claude Code. Most terminals do this whenever an application requests it. iTerm2 makes it a per-profile setting: if the wheel does nothing but `PgUp` and `PgDn` work, open Settings → Profiles → Terminal and turn on Enable mouse reporting. The same setting is also required for click-to-expand and text selection to work.

85 

86If mouse wheel scrolling feels slow, your terminal may be sending one scroll event per physical notch with no multiplier. Some terminals, like Ghostty and iTerm2 with faster scrolling enabled, already amplify wheel events. Others, including the VS Code integrated terminal, send exactly one event per notch. Claude Code cannot detect which.

87 

88Set `CLAUDE_CODE_SCROLL_SPEED` to multiply the base scroll distance:

89 

90```bash theme={null}

91export CLAUDE_CODE_SCROLL_SPEED=3

92```

93 

94A value of `3` matches the default in `vim` and similar applications. The setting accepts values from 1 to 20.

95 

96## Search and review the conversation

97 

98`Ctrl+o` toggles between the normal prompt and transcript mode. For a quieter view that shows only your last prompt, a one-line summary of tool calls with edit diffstats, and the final response, run `/focus`. The setting persists across sessions. Run `/focus` again to turn it off.

99 

100Transcript mode gains `less`-style navigation and search:

101 

102| Key | Action |

103| :----------------------------------- | :----------------------------------------------------------------------------------------------------- |

104| `/` | Open search. Type to find matches, `Enter` to accept, `Esc` to cancel and restore your scroll position |

105| `n` / `N` | Jump to next or previous match. Works after you've closed the search bar |

106| `j` / `k` or `↑` / `↓` | Scroll one line |

107| `g` / `G` or `Home` / `End` | Jump to top or bottom |

108| `Ctrl+u` / `Ctrl+d` | Scroll half a page |

109| `Ctrl+b` / `Ctrl+f` or `Space` / `b` | Scroll a full page |

110| `Ctrl+o`, `Esc`, or `q` | Exit transcript mode and return to the prompt |

111 

112Your terminal's `Cmd+f` and tmux search don't see the conversation because it lives in the alternate screen buffer, not the native scrollback. To hand the content back to your terminal, press `Ctrl+o` to enter transcript mode first, then:

113 

114* **`[`**: writes the full conversation into your terminal's native scrollback buffer, with all tool output expanded. The conversation is now ordinary text in your terminal, so `Cmd+f`, tmux copy mode, and any other native tool can search or select it. Long sessions may pause for a moment while this happens. This lasts until you exit transcript mode with `Esc` or `q`, which returns you to fullscreen rendering. The next `Ctrl+o` starts fresh.

115* **`v`**: writes the conversation to a temporary file and opens it in `$VISUAL` or `$EDITOR`.

116 

117Press `Esc` or `q` to return to the prompt.

118 

119## Use with tmux

120 

121Fullscreen rendering works inside tmux, with two caveats.

122 

123Mouse wheel scrolling requires tmux's mouse mode. If your `~/.tmux.conf` does not already enable it, add this line and reload your config:

124 

125```bash theme={null}

126set -g mouse on

127```

128 

129Without mouse mode, wheel events go to tmux instead of Claude Code. Keyboard scrolling with `PgUp` and `PgDn` works either way. Claude Code prints a one-time hint at startup if it detects tmux with mouse mode off.

130 

131Fullscreen rendering is incompatible with iTerm2's tmux integration mode, which is the mode you enter with `tmux -CC`. In integration mode, iTerm2 renders each tmux pane as a native split rather than letting tmux draw to the terminal. The alternate screen buffer and mouse tracking do not work correctly there: the mouse wheel does nothing, and double-click can corrupt the terminal state. Don't enable fullscreen rendering in `tmux -CC` sessions. Regular tmux inside iTerm2, without `-CC`, works fine.

132 

133## Keep native text selection

134 

135Mouse capture is the most common friction point, especially over SSH or inside tmux. When Claude Code captures mouse events, your terminal's native copy-on-select stops working. The selection you make with click-and-drag exists inside Claude Code, not in your terminal's selection buffer, so tmux copy mode, Kitty hints, and similar tools don't see it.

136 

137Claude Code tries to write the selection to your clipboard, but the path it uses depends on your setup. Inside tmux it writes to the tmux paste buffer. Over SSH it falls back to OSC 52 escape sequences, which some terminals block by default. Claude Code prints a toast after each copy telling you which path it used.

138 

139If you rely on your terminal's native selection, set `CLAUDE_CODE_DISABLE_MOUSE=1` to opt out of mouse capture while keeping the flicker-free rendering and flat memory:

140 

141```bash theme={null}

142CLAUDE_CODE_NO_FLICKER=1 CLAUDE_CODE_DISABLE_MOUSE=1 claude

143```

144 

145With mouse capture disabled, keyboard scrolling with `PgUp`, `PgDn`, `Ctrl+Home`, and `Ctrl+End` still works, and your terminal handles selection natively. You lose click-to-position-cursor, click-to-expand tool output, URL clicking, and wheel scrolling inside Claude Code.

146 

147## Research preview

148 

149Fullscreen rendering is a research preview feature. It has been tested on common terminal emulators, but you may encounter rendering issues on less common terminals or unusual configurations.

150 

151If you encounter a problem, run `/feedback` inside Claude Code to report it, or open an issue on the [claude-code GitHub repo](https://github.com/anthropics/claude-code/issues). Include your terminal emulator name and version.

152 

153To turn fullscreen rendering off, run `/tui default`, or unset the environment variable if you enabled it that way.

github-actions.md +18 −21

Details

6 6 

7> Learn about integrating Claude Code into your development workflow with Claude Code GitHub Actions7> Learn about integrating Claude Code into your development workflow with Claude Code GitHub Actions

8 8 

9Claude Code GitHub Actions brings AI-powered automation to your GitHub workflow. With a simple `@claude` mention in any PR or issue, Claude can analyze your code, create pull requests, implement features, and fix bugs - all while following your project's standards.9Claude Code GitHub Actions brings AI-powered automation to your GitHub workflow. With a simple `@claude` mention in any PR or issue, Claude can analyze your code, create pull requests, implement features, and fix bugs - all while following your project's standards. For automatic reviews posted on every PR without a trigger, see [GitHub Code Review](/en/code-review).

10 10 

11<Note>11<Note>

12 Claude Code GitHub Actions is built on top of the [Claude Code12 Claude Code GitHub Actions is built on top of the [Claude Agent SDK](/en/agent-sdk/overview), which enables programmatic integration of Claude Code into your applications. You can use the SDK to build custom automation workflows beyond GitHub Actions.

13 SDK](https://docs.claude.com/en/docs/agent-sdk), which enables programmatic integration of

14 Claude Code into your applications. You can use the SDK to build custom

15 automation workflows beyond GitHub Actions.

16</Note>13</Note>

17 14 

18<Info>15<Info>

19 **Claude Opus 4.5 is now available.** Claude Code GitHub Actions default to Sonnet. To use Opus 4.5, configure the [model parameter](#breaking-changes-reference) to use `claude-opus-4-5-20251101`.16 **Claude Opus 4.7 is now available.** Claude Code GitHub Actions default to Sonnet. To use Opus 4.7, configure the [model parameter](#breaking-changes-reference) to use `claude-opus-4-7`.

20</Info>17</Info>

21 18 

22## Why use Claude Code GitHub Actions?19## Why use Claude Code GitHub Actions?


117 anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}114 anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

118 custom_instructions: "Follow our coding standards"115 custom_instructions: "Follow our coding standards"

119 max_turns: "10"116 max_turns: "10"

120 model: "claude-sonnet-4-5-20250929"117 model: "claude-sonnet-4-6"

121```118```

122 119 

123**GA version (v1.0):**120**GA version (v1.0):**


130 claude_args: |127 claude_args: |

131 --append-system-prompt "Follow our coding standards"128 --append-system-prompt "Follow our coding standards"

132 --max-turns 10129 --max-turns 10

133 --model claude-sonnet-4-5-20250929130 --model claude-sonnet-4-6

134```131```

135 132 

136<Tip>133<Tip>


174 - uses: anthropics/claude-code-action@v1171 - uses: anthropics/claude-code-action@v1

175 with:172 with:

176 anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}173 anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

177 prompt: "/review"174 prompt: "Review this pull request for code quality, correctness, and security. Analyze the diff, then post your findings as review comments."

178 claude_args: "--max-turns 5"175 claude_args: "--max-turns 5"

179```176```

180 177 


193 with:190 with:

194 anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}191 anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

195 prompt: "Generate a summary of yesterday's commits and open issues"192 prompt: "Generate a summary of yesterday's commits and open issues"

196 claude_args: "--model claude-opus-4-5-20251101"193 claude_args: "--model opus"

197```194```

198 195 

199### Common use cases196### Common use cases

200 197 

201In issue or PR comments:198In issue or PR comments:

202 199 

203```200```text theme={null}

204@claude implement this feature based on the issue description201@claude implement this feature based on the issue description

205@claude how should I implement user authentication for this endpoint?202@claude how should I implement user authentication for this endpoint?

206@claude fix the TypeError in the user dashboard component203@claude fix the TypeError in the user dashboard component


270Key features:267Key features:

271 268 

272* **Unified prompt interface** - Use `prompt` for all instructions269* **Unified prompt interface** - Use `prompt` for all instructions

273* **Commands** - Prebuilt prompts like `/review` or `/fix`270* **Skills** - Invoke installed [skills](/en/skills) directly from the prompt

274* **CLI passthrough** - Any Claude Code CLI argument via `claude_args`271* **CLI passthrough** - Any Claude Code CLI argument via `claude_args`

275* **Flexible triggers** - Works with any GitHub event272* **Flexible triggers** - Works with any GitHub event

276 273 


521 with:518 with:

522 github_token: ${{ steps.app-token.outputs.token }}519 github_token: ${{ steps.app-token.outputs.token }}

523 use_bedrock: "true"520 use_bedrock: "true"

524 claude_args: '--model us.anthropic.claude-sonnet-4-5-20250929-v1:0 --max-turns 10'521 claude_args: '--model us.anthropic.claude-sonnet-4-6 --max-turns 10'

525 ```522 ```

526 523 

527 <Tip>524 <Tip>

528 The model ID format for Bedrock includes the region prefix (e.g., `us.anthropic.claude...`) and version suffix.525 The model ID format for Bedrock includes a region prefix (for example, `us.anthropic.claude-sonnet-4-6`).

529 </Tip>526 </Tip>

530 </Accordion>527 </Accordion>

531 528 


592 github_token: ${{ steps.app-token.outputs.token }}589 github_token: ${{ steps.app-token.outputs.token }}

593 trigger_phrase: "@claude"590 trigger_phrase: "@claude"

594 use_vertex: "true"591 use_vertex: "true"

595 claude_args: '--model claude-sonnet-4@20250514 --max-turns 10'592 claude_args: '--model claude-sonnet-4-5@20250929 --max-turns 10'

596 env:593 env:

597 ANTHROPIC_VERTEX_PROJECT_ID: ${{ steps.auth.outputs.project_id }}594 ANTHROPIC_VERTEX_PROJECT_ID: ${{ steps.auth.outputs.project_id }}

598 CLOUD_ML_REGION: us-east5595 CLOUD_ML_REGION: us-east5

599 VERTEX_REGION_CLAUDE_3_7_SONNET: us-east5596 VERTEX_REGION_CLAUDE_4_5_SONNET: us-east5

600 ```597 ```

601 598 

602 <Tip>599 <Tip>


628The Claude Code Action v1 uses a simplified configuration:625The Claude Code Action v1 uses a simplified configuration:

629 626 

630| Parameter | Description | Required |627| Parameter | Description | Required |

631| ------------------- | ------------------------------------------------------ | -------- |628| ------------------- | ------------------------------------------------------------------ | -------- |

632| `prompt` | Instructions for Claude (text or skill like `/review`) | No\* |629| `prompt` | Instructions for Claude (plain text or a [skill](/en/skills) name) | No\* |

633| `claude_args` | CLI arguments passed to Claude Code | No |630| `claude_args` | CLI arguments passed to Claude Code | No |

634| `anthropic_api_key` | Claude API key | Yes\*\* |631| `anthropic_api_key` | Claude API key | Yes\*\* |

635| `github_token` | GitHub token for API access | No |632| `github_token` | GitHub token for API access | No |


645The `claude_args` parameter accepts any Claude Code CLI arguments:642The `claude_args` parameter accepts any Claude Code CLI arguments:

646 643 

647```yaml theme={null}644```yaml theme={null}

648claude_args: "--max-turns 5 --model claude-sonnet-4-5-20250929 --mcp-config /path/to/config.json"645claude_args: "--max-turns 5 --model claude-sonnet-4-6 --mcp-config /path/to/config.json"

649```646```

650 647 

651Common arguments:648Common arguments:

652 649 

653* `--max-turns`: Maximum conversation turns (default: 10)650* `--max-turns`: Maximum conversation turns (default: 10)

654* `--model`: Model to use (for example, `claude-sonnet-4-5-20250929`)651* `--model`: Model to use (for example, `claude-sonnet-4-6`)

655* `--mcp-config`: Path to MCP configuration652* `--mcp-config`: Path to MCP configuration

656* `--allowed-tools`: Comma-separated list of allowed tools653* `--allowedTools`: Comma-separated list of allowed tools. The `--allowed-tools` alias also works.

657* `--debug`: Enable debug output654* `--debug`: Enable debug output

658 655 

659### Alternative integration methods656### Alternative integration methods

github-enterprise-server.md +188 −0 added

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# Claude Code with GitHub Enterprise Server

6 

7> Connect Claude Code to your self-hosted GitHub Enterprise Server instance for web sessions, code review, and plugin marketplaces.

8 

9<Note>

10 GitHub Enterprise Server support is available for Team and Enterprise plans.

11</Note>

12 

13GitHub Enterprise Server (GHES) support lets your organization use Claude Code with repositories hosted on your self-managed GitHub instance instead of github.com. Once an admin connects your GHES instance, developers can run web sessions, get automated code reviews, and install plugins from internal marketplaces without any per-repository configuration.

14 

15For repositories on github.com, see [Claude Code on the web](/en/claude-code-on-the-web) and [Code Review](/en/code-review). To run Claude in your own CI infrastructure, see [GitHub Actions](/en/github-actions).

16 

17## What works with GitHub Enterprise Server

18 

19The table below shows which Claude Code features support GHES and any differences from github.com behavior.

20 

21| Feature | GHES support | Notes |

22| :--------------------- | :-------------- | :--------------------------------------------------------------------------------------------------------------------------- |

23| Claude Code on the web | ✅ Supported | Admin connects the GHES instance once; developers use `claude --remote` or [claude.ai/code](https://claude.ai/code) as usual |

24| Code Review | ✅ Supported | Same automated PR reviews as github.com |

25| Teleport sessions | ✅ Supported | Move sessions between web and terminal with `--teleport` |

26| Plugin marketplaces | ✅ Supported | Use full git URLs instead of `owner/repo` shorthand |

27| Contribution metrics | ✅ Supported | Delivered via webhooks to the [analytics dashboard](/en/analytics) |

28| GitHub Actions | ✅ Supported | Requires manual workflow setup; `/install-github-app` is github.com only |

29| GitHub MCP server | ❌ Not supported | The GitHub MCP server does not work with GHES instances |

30 

31## Admin setup

32 

33An admin connects your GHES instance to Claude Code once. After that, developers in your organization can use GHES repositories without any additional configuration. You need admin access to your Claude organization and permission to create GitHub Apps on your GHES instance.

34 

35The guided setup generates a GitHub App manifest and redirects you to your GHES instance to create the app in one click. If your environment blocks the redirect flow, an [alternative manual setup](#manual-setup) is available.

36 

37<Steps>

38 <Step title="Open Claude Code admin settings">

39 Go to [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code) and find the GitHub Enterprise Server section.

40 </Step>

41 

42 <Step title="Start the guided setup">

43 Click **Connect**. Enter a display name for the connection and your GHES hostname, for example `github.example.com`. If your GHES instance uses a self-signed or private certificate authority, paste the CA certificate in the optional field.

44 </Step>

45 

46 <Step title="Create the GitHub App">

47 Click **Continue to GitHub Enterprise**. Your browser redirects to your GHES instance with a pre-filled app manifest. Review the configuration and click **Create GitHub App**. GHES redirects you back to Claude with the app credentials stored automatically.

48 </Step>

49 

50 <Step title="Install the app on your repositories">

51 From the GitHub App page on your GHES instance, install the app on the repositories or organizations you want Claude to access. You can start with a subset and add more later.

52 </Step>

53 

54 <Step title="Enable features">

55 Return to [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code) and enable [Code Review](/en/code-review#set-up-code-review) and [contribution metrics](/en/analytics#enable-contribution-metrics) for your GHES repositories using the same configuration as github.com.

56 </Step>

57</Steps>

58 

59### GitHub App permissions

60 

61The manifest configures the GitHub App with the permissions and webhook events Claude needs across web sessions, Code Review, and contribution metrics:

62 

63| Permission | Access | Used for |

64| :--------------- | :------------- | :------------------------------------------ |

65| Contents | Read and write | Cloning repositories and pushing branches |

66| Pull requests | Read and write | Creating PRs and posting review comments |

67| Issues | Read and write | Responding to issue mentions |

68| Checks | Read and write | Posting Code Review check runs |

69| Actions | Read | Reading CI status for auto-fix |

70| Repository hooks | Read and write | Receiving webhooks for contribution metrics |

71| Metadata | Read | Required by GitHub for all apps |

72 

73The app subscribes to `pull_request`, `issue_comment`, `pull_request_review_comment`, `pull_request_review`, and `check_run` events.

74 

75### Manual setup

76 

77If the guided redirect flow is blocked by your network configuration, click **Add manually** instead of Connect. Create a GitHub App on your GHES instance with the [permissions and events above](#github-app-permissions), then enter the app credentials in the form: hostname, OAuth client ID and secret, GitHub App ID, client ID, client secret, webhook secret, and private key.

78 

79### Network requirements

80 

81Your GHES instance must be reachable from Anthropic infrastructure so Claude can clone repositories and post review comments. If your GHES instance is behind a firewall, allowlist the [Anthropic API IP addresses](https://platform.claude.com/docs/en/api/ip-addresses).

82 

83## Developer workflow

84 

85Once your admin has connected the GHES instance, no developer-side configuration is needed. Claude Code detects your GHES hostname automatically from the git remote in your working directory.

86 

87Clone a repository from your GHES instance as you normally would:

88 

89```bash theme={null}

90git clone git@github.example.com:platform/api-service.git

91cd api-service

92```

93 

94Then start a web session. Claude detects the GHES host from your git remote and routes the session through your organization's configured instance:

95 

96```bash theme={null}

97claude --remote "Add retry logic to the payment webhook handler"

98```

99 

100The session runs on Anthropic infrastructure, clones your repository from GHES, and pushes changes back to a branch. Monitor progress with `/tasks` or at [claude.ai/code](https://claude.ai/code). See [Claude Code on the web](/en/claude-code-on-the-web) for the full remote session workflow including diff review, auto-fix, and routines.

101 

102### Teleport sessions to your terminal

103 

104Pull a web session into your local terminal with `claude --teleport`. Teleport verifies you're in a checkout of the same GHES repository before fetching the branch and loading the session history. See [teleport requirements](/en/claude-code-on-the-web#teleport-requirements) for details.

105 

106## Plugin marketplaces on GHES

107 

108Host plugin marketplaces on your GHES instance to distribute internal tooling across your organization. The marketplace structure is identical to github.com-hosted marketplaces; the only difference is how you reference them.

109 

110### Add a GHES marketplace

111 

112The `owner/repo` shorthand always resolves to github.com. For GHES-hosted marketplaces, use the full git URL:

113 

114```bash theme={null}

115/plugin marketplace add git@github.example.com:platform/claude-plugins.git

116```

117 

118HTTPS URLs work as well:

119 

120```bash theme={null}

121/plugin marketplace add https://github.example.com/platform/claude-plugins.git

122```

123 

124See [Create and distribute a plugin marketplace](/en/plugin-marketplaces) for the full guide to building marketplaces.

125 

126### Allowlist GHES marketplaces in managed settings

127 

128If your organization uses [managed settings](/en/settings) to restrict which marketplaces developers can add, use the `hostPattern` source type to allow all marketplaces from your GHES instance without enumerating each repository:

129 

130```json theme={null}

131{

132 "strictKnownMarketplaces": [

133 {

134 "source": "hostPattern",

135 "hostPattern": "^github\\.example\\.com$"

136 }

137 ]

138}

139```

140 

141You can also pre-register marketplaces for developers so they appear without manual setup. This example makes an internal tools marketplace available organization-wide:

142 

143```json theme={null}

144{

145 "extraKnownMarketplaces": {

146 "internal-tools": {

147 "source": {

148 "source": "git",

149 "url": "git@github.example.com:platform/claude-plugins.git"

150 }

151 }

152 }

153}

154```

155 

156See the [strictKnownMarketplaces](/en/settings#strictknownmarketplaces) and [extraKnownMarketplaces](/en/settings#extraknownmarketplaces) settings reference for the complete schema.

157 

158## Limitations

159 

160A few features behave differently on GHES than on github.com. The [feature table](#what-works-with-github-enterprise-server) summarizes support; this section covers the workarounds.

161 

162* **`/install-github-app` command**: follow the [admin setup](#admin-setup) flow on claude.ai instead. If you also want GitHub Actions workflows on GHES, adapt the [example workflow](https://github.com/anthropics/claude-code-action/blob/main/examples/claude.yml) manually.

163* **GitHub MCP server**: use the `gh` CLI configured for your GHES host instead. Run `gh auth login --hostname github.example.com` to authenticate, then Claude can use `gh` commands in sessions.

164 

165## Troubleshooting

166 

167### Web session fails to clone repository

168 

169If `claude --remote` fails with a clone error, verify that your admin has completed setup for your GHES instance and that the GitHub App is installed on the repository you're working in. Check with your admin that the instance hostname registered in Claude settings matches the hostname in your git remote.

170 

171### Marketplace add fails with a policy error

172 

173If `/plugin marketplace add` is blocked for your GHES URL, your organization has restricted marketplace sources. Ask your admin to add a `hostPattern` entry for your GHES hostname in [managed settings](#allowlist-ghes-marketplaces-in-managed-settings).

174 

175### GHES instance not reachable

176 

177If reviews or web sessions time out, your GHES instance may not be reachable from Anthropic infrastructure. Confirm your firewall allows inbound connections from the [Anthropic API IP addresses](https://platform.claude.com/docs/en/api/ip-addresses).

178 

179## Related resources

180 

181These pages cover the features referenced throughout this guide in more depth:

182 

183* [Claude Code on the web](/en/claude-code-on-the-web): run Claude Code sessions on cloud infrastructure

184* [Code Review](/en/code-review): automated PR reviews

185* [Plugin marketplaces](/en/plugin-marketplaces): build and distribute plugin catalogs

186* [Analytics](/en/analytics): track usage and contribution metrics

187* [Managed settings](/en/settings): organization-wide policy configuration

188* [Network configuration](/en/network-config): firewall and IP allowlist requirements

gitlab-ci-cd.md +6 −6

Details

13</Info>13</Info>

14 14 

15<Note>15<Note>

16 This integration is built on top of the [Claude Code CLI and SDK](https://docs.claude.com/en/docs/agent-sdk), enabling programmatic use of Claude in your CI/CD jobs and custom automation workflows.16 This integration is built on top of the [Claude Code CLI and Agent SDK](/en/agent-sdk/overview), enabling programmatic use of Claude in your CI/CD jobs and custom automation workflows.

17</Note>17</Note>

18 18 

19## Why use Claude Code with GitLab?19## Why use Claude Code with GitLab?


126 126 

127In an issue comment:127In an issue comment:

128 128 

129```129```text theme={null}

130@claude implement this feature based on the issue description130@claude implement this feature based on the issue description

131```131```

132 132 


136 136 

137In an MR discussion:137In an MR discussion:

138 138 

139```139```text theme={null}

140@claude suggest a concrete approach to cache the results of this API call140@claude suggest a concrete approach to cache the results of this API call

141```141```

142 142 


146 146 

147In an issue or MR comment:147In an issue or MR comment:

148 148 

149```149```text theme={null}

150@claude fix the TypeError in the user dashboard component150@claude fix the TypeError in the user dashboard component

151```151```

152 152 


319```319```

320 320 

321<Note>321<Note>

322 Model IDs for Bedrock include region-specific prefixes and version suffixes (for example, `us.anthropic.claude-sonnet-4-5-20250929-v1:0`). Pass the desired model via your job configuration or prompt if your workflow supports it.322 Model IDs for Bedrock include region-specific prefixes (for example, `us.anthropic.claude-sonnet-4-6`). Pass the desired model via your job configuration or prompt if your workflow supports it.

323</Note>323</Note>

324 324 

325### Google Vertex AI job example (Workload Identity Federation)325### Google Vertex AI job example (Workload Identity Federation)


408* **API costs**:408* **API costs**:

409 * Each Claude interaction consumes tokens based on prompt and response size409 * Each Claude interaction consumes tokens based on prompt and response size

410 * Token usage varies by task complexity and codebase size410 * Token usage varies by task complexity and codebase size

411 * See [Anthropic pricing](https://docs.claude.com/en/docs/about-claude/pricing) for details411 * See [Anthropic pricing](https://platform.claude.com/docs/en/about-claude/pricing) for details

412 412 

413* **Cost optimization tips**:413* **Cost optimization tips**:

414 * Use specific `@claude` commands to reduce unnecessary turns414 * Use specific `@claude` commands to reduce unnecessary turns

Details

6 6 

7> Learn about configuring Claude Code through Google Vertex AI, including setup, IAM configuration, and troubleshooting.7> Learn about configuring Claude Code through Google Vertex AI, including setup, IAM configuration, and troubleshooting.

8 8 

9 

10 

11<Experiment flag="docs-contact-sales-cta" treatment={<ContactSalesCard surface="vertex" />} />

12 

9## Prerequisites13## Prerequisites

10 14 

11Before configuring Claude Code with Vertex AI, ensure you have:15Before configuring Claude Code with Vertex AI, ensure you have:

12 16 

13* A Google Cloud Platform (GCP) account with billing enabled17* A Google Cloud Platform (GCP) account with billing enabled

14* A GCP project with Vertex AI API enabled18* A GCP project with Vertex AI API enabled

15* Access to desired Claude models (for example, Claude Sonnet 4.5)19* Access to desired Claude models (for example, Claude Sonnet 4.6)

16* Google Cloud SDK (`gcloud`) installed and configured20* Google Cloud SDK (`gcloud`) installed and configured

17* Quota allocated in desired GCP region21* Quota allocated in desired GCP region

18 22 

19## Region Configuration23To sign in with your own Vertex AI credentials, follow [Sign in with Vertex AI](#sign-in-with-vertex-ai) below. To deploy Claude Code across a team, use the [manual setup](#set-up-manually) steps and [pin your model versions](#5-pin-model-versions) before rolling out.

20 24 

21Claude Code can be used with both Vertex AI [global](https://cloud.google.com/blog/products/ai-machine-learning/global-endpoint-for-claude-models-generally-available-on-vertex-ai) and regional endpoints.25## Sign in with Vertex AI

26 

27If you have Google Cloud credentials and want to start using Claude Code through Vertex AI, the login wizard walks you through it. You complete the GCP-side prerequisites once per project; the wizard handles the Claude Code side.

22 28 

23<Note>29<Note>

24 Vertex AI may not support the Claude Code default models on all regions. You may need to switch to a [supported region or model](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations#genai-partner-models).30 The Vertex AI setup wizard requires Claude Code v2.1.98 or later. Run `claude --version` to check.

25</Note>31</Note>

26 32 

33<Steps>

34 <Step title="Enable Claude models in your GCP project">

35 [Enable the Vertex AI API](#1-enable-vertex-ai-api) for your project, then request access to the Claude models you want in the [Vertex AI Model Garden](https://console.cloud.google.com/vertex-ai/model-garden). See [IAM configuration](#iam-configuration) for the permissions your account needs.

36 </Step>

37 

38 <Step title="Start Claude Code and choose Vertex AI">

39 Run `claude`. At the login prompt, select **3rd-party platform**, then **Google Vertex AI**.

40 </Step>

41 

42 <Step title="Follow the wizard prompts">

43 Choose how you authenticate to Google Cloud: Application Default Credentials from `gcloud`, a service account key file, or credentials already in your environment. The wizard detects your project and region, verifies which Claude models your project can invoke, and lets you pin them. It saves the result to the `env` block of your [user settings file](/en/settings), so you don't need to export environment variables yourself.

44 </Step>

45</Steps>

46 

47After you've signed in, run `/setup-vertex` any time to reopen the wizard and change your credentials, project, region, or model pins.

48 

49## Region configuration

50 

51Claude Code supports Vertex AI [global](https://cloud.google.com/blog/products/ai-machine-learning/global-endpoint-for-claude-models-generally-available-on-vertex-ai), multi-region, and regional endpoints. Set `CLOUD_ML_REGION` to `global`, a multi-region location such as `eu` or `us`, or a specific region such as `us-east5`. Claude Code selects the correct Vertex AI hostname for each form, including the `aiplatform.eu.rep.googleapis.com` and `aiplatform.us.rep.googleapis.com` hosts for multi-region locations.

52 

27<Note>53<Note>

28 Vertex AI may not support the Claude Code default models on global endpoints. You may need to switch to a regional endpoint or [supported model](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#supported_models).54 Vertex AI may not support the Claude Code default models on every endpoint type. Model availability varies across [specific regions](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations#genai-partner-models), multi-region locations, and [global endpoints](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#supported_models). You may need to switch to a supported location or specify a supported model.

29</Note>55</Note>

30 56 

31## Setup57## Set up manually

58 

59To configure Vertex AI through environment variables instead of the wizard, for example in CI or a scripted enterprise rollout, follow the steps below.

32 60 

33### 1. Enable Vertex AI API61### 1. Enable Vertex AI API

34 62 


48 76 

491. Navigate to the [Vertex AI Model Garden](https://console.cloud.google.com/vertex-ai/model-garden)771. Navigate to the [Vertex AI Model Garden](https://console.cloud.google.com/vertex-ai/model-garden)

502. Search for "Claude" models782. Search for "Claude" models

513. Request access to desired Claude models (for example, Claude Sonnet 4.5)793. Request access to desired Claude models (for example, Claude Sonnet 4.6)

524. Wait for approval (may take 24-48 hours)804. Wait for approval (may take 24-48 hours)

53 81 

54### 3. Configure GCP credentials82### 3. Configure GCP credentials


71export CLOUD_ML_REGION=global99export CLOUD_ML_REGION=global

72export ANTHROPIC_VERTEX_PROJECT_ID=YOUR-PROJECT-ID100export ANTHROPIC_VERTEX_PROJECT_ID=YOUR-PROJECT-ID

73 101 

102# Optional: Override the Vertex endpoint URL for custom endpoints or gateways

103# export ANTHROPIC_VERTEX_BASE_URL=https://aiplatform.googleapis.com

104 

74# Optional: Disable prompt caching if needed105# Optional: Disable prompt caching if needed

75export DISABLE_PROMPT_CACHING=1106export DISABLE_PROMPT_CACHING=1

76 107 

77# When CLOUD_ML_REGION=global, override region for unsupported models108# Optional: Request 1-hour prompt cache TTL instead of the 5-minute default

78export VERTEX_REGION_CLAUDE_3_5_HAIKU=us-east5109export ENABLE_PROMPT_CACHING_1H=1

79 110 

80# Optional: Override regions for other specific models111# When CLOUD_ML_REGION=global, override region for models that don't support global endpoints

81export VERTEX_REGION_CLAUDE_3_5_SONNET=us-east5112export VERTEX_REGION_CLAUDE_HAIKU_4_5=us-east5

82export VERTEX_REGION_CLAUDE_3_7_SONNET=us-east5113export VERTEX_REGION_CLAUDE_4_6_SONNET=europe-west1

83export VERTEX_REGION_CLAUDE_4_0_OPUS=europe-west1

84export VERTEX_REGION_CLAUDE_4_0_SONNET=us-east5

85export VERTEX_REGION_CLAUDE_4_1_OPUS=europe-west1

86```114```

87 115 

88<Note>116Most model versions have a corresponding `VERTEX_REGION_CLAUDE_*` variable. See the [Environment variables reference](/en/env-vars) for the full list. Check [Vertex Model Garden](https://console.cloud.google.com/vertex-ai/model-garden) to determine which models support global endpoints versus regional only.

89 [Prompt caching](https://docs.claude.com/en/docs/build-with-claude/prompt-caching) is automatically supported when you specify the `cache_control` ephemeral flag. To disable it, set `DISABLE_PROMPT_CACHING=1`. For heightened rate limits, contact Google Cloud support.

90</Note>

91 117 

92<Note>118[Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) is enabled automatically. To disable it, set `DISABLE_PROMPT_CACHING=1`. To request a 1-hour cache TTL instead of the 5-minute default, set `ENABLE_PROMPT_CACHING_1H=1`; cache writes with a 1-hour TTL are billed at a higher rate. For heightened rate limits, contact Google Cloud support. When using Vertex AI, the `/login` and `/logout` commands are disabled since authentication is handled through Google Cloud credentials.

93 When using Vertex AI, the `/login` and `/logout` commands are disabled since authentication is handled through Google Cloud credentials.119 

94</Note>120[MCP tool search](/en/mcp#scale-with-mcp-tool-search) is disabled by default on Vertex AI because the endpoint does not accept the required beta header. All MCP tool definitions load upfront instead. To opt in, set `ENABLE_TOOL_SEARCH=true`.

95 121 

96### 5. Model configuration122### 5. Pin model versions

97 123 

98Claude Code uses these default models for Vertex AI:124<Warning>

125 Pin specific model versions when deploying to multiple users. Without pinning, model aliases such as `sonnet` and `opus` resolve to the latest version, which may not yet be enabled in your Vertex AI project when Anthropic releases an update. Claude Code [falls back](#startup-model-checks) to the previous version at startup when the latest is unavailable, but pinning lets you control when your users move to a new model.

126</Warning>

127 

128Set these environment variables to specific Vertex AI model IDs.

129 

130Without `ANTHROPIC_DEFAULT_OPUS_MODEL`, the `opus` alias on Vertex resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:

131 

132```bash theme={null}

133export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7'

134export ANTHROPIC_DEFAULT_SONNET_MODEL='claude-sonnet-4-6'

135export ANTHROPIC_DEFAULT_HAIKU_MODEL='claude-haiku-4-5@20251001'

136```

137 

138For current and legacy model IDs, see [Models overview](https://platform.claude.com/docs/en/about-claude/models/overview). See [Model configuration](/en/model-config#pin-models-for-third-party-deployments) for the full list of environment variables.

139 

140Claude Code uses these default models when no pinning variables are set:

99 141 

100| Model type | Default value |142| Model type | Default value |

101| :--------------- | :--------------------------- |143| :--------------- | :--------------------------- |

102| Primary model | `claude-sonnet-4-5@20250929` |144| Primary model | `claude-sonnet-4-5@20250929` |

103| Small/fast model | `claude-haiku-4-5@20251001` |145| Small/fast model | `claude-haiku-4-5@20251001` |

104 146 

105<Note>147To customize models further:

106 For Vertex AI users, Claude Code will not automatically upgrade from Haiku 3.5 to Haiku 4.5. To manually switch to a newer Haiku model, set the `ANTHROPIC_DEFAULT_HAIKU_MODEL` environment variable to the full model name (for example, `claude-haiku-4-5@20251001`).

107</Note>

108 

109To customize models:

110 148 

111```bash theme={null}149```bash theme={null}

112export ANTHROPIC_MODEL='claude-opus-4-1@20250805'150export ANTHROPIC_MODEL='claude-opus-4-7'

113export ANTHROPIC_SMALL_FAST_MODEL='claude-haiku-4-5@20251001'151export ANTHROPIC_DEFAULT_HAIKU_MODEL='claude-haiku-4-5@20251001'

114```152```

115 153 

154## Startup model checks

155 

156When Claude Code starts with Vertex AI configured, it verifies that the models it intends to use are accessible in your project. This check requires Claude Code v2.1.98 or later.

157 

158If you have pinned a model version that is older than the current Claude Code default, and your project can invoke the newer version, Claude Code prompts you to update the pin. Accepting writes the new model ID to your [user settings file](/en/settings) and restarts Claude Code. Declining is remembered until the next default version change.

159 

160If you have not pinned a model and the current default is unavailable in your project, Claude Code falls back to the previous version for the current session and shows a notice. The fallback is not persisted. Enable the newer model in [Model Garden](https://console.cloud.google.com/vertex-ai/model-garden) or [pin a version](#5-pin-model-versions) to make the choice permanent.

161 

116## IAM configuration162## IAM configuration

117 163 

118Assign the required IAM permissions:164Assign the required IAM permissions:


126For details, see [Vertex IAM documentation](https://cloud.google.com/vertex-ai/docs/general/access-control).172For details, see [Vertex IAM documentation](https://cloud.google.com/vertex-ai/docs/general/access-control).

127 173 

128<Note>174<Note>

129 We recommend creating a dedicated GCP project for Claude Code to simplify cost tracking and access control.175 Create a dedicated GCP project for Claude Code to simplify cost tracking and access control.

130</Note>176</Note>

131 177 

132## 1M token context window178## 1M token context window

133 179 

134Claude Sonnet 4 and Sonnet 4.5 support the [1M token context window](https://docs.claude.com/en/docs/build-with-claude/context-windows#1m-token-context-window) on Vertex AI.180Claude Opus 4.7, Opus 4.6, and Sonnet 4.6 support the [1M token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#1m-token-context-window) on Vertex AI. Claude Code automatically enables the extended context window when you select a 1M model variant.

135 181 

136<Note>182The [setup wizard](#sign-in-with-vertex-ai) offers a 1M context option when it pins models. To enable it for a manually pinned model instead, append `[1m]` to the model ID. See [Pin models for third-party deployments](/en/model-config#pin-models-for-third-party-deployments) for details.

137 The 1M token context window is currently in beta. To use the extended context window, include the `context-1m-2025-08-07` beta header in your Vertex AI requests.

138</Note>

139 183 

140## Troubleshooting184## Troubleshooting

141 185 


146If you encounter "model not found" 404 errors:190If you encounter "model not found" 404 errors:

147 191 

148* Confirm model is Enabled in [Model Garden](https://console.cloud.google.com/vertex-ai/model-garden)192* Confirm model is Enabled in [Model Garden](https://console.cloud.google.com/vertex-ai/model-garden)

149* Verify you have access to the specified region193* Verify the model is available in the location you specified. Some models are offered only on `global` or multi-region locations such as `eu` and `us`, not in specific regions

150* If using `CLOUD_ML_REGION=global`, check that your models support global endpoints in [Model Garden](https://console.cloud.google.com/vertex-ai/model-garden) under "Supported features". For models that don't support global endpoints, either:194* If using `CLOUD_ML_REGION=global`, check that your models support global endpoints in [Model Garden](https://console.cloud.google.com/vertex-ai/model-garden) under "Supported features". For models that don't support global endpoints, either:

151 * Specify a supported model via `ANTHROPIC_MODEL` or `ANTHROPIC_SMALL_FAST_MODEL`, or195 * Specify a supported model via `ANTHROPIC_MODEL` or `ANTHROPIC_DEFAULT_HAIKU_MODEL`, or

152 * Set a regional endpoint using `VERTEX_REGION_<MODEL_NAME>` environment variables196 * Set a region or multi-region location using `VERTEX_REGION_<MODEL_NAME>` environment variables

153 197 

154If you encounter 429 errors:198If you encounter 429 errors:

155 199 

headless.md +76 −22

Details

6 6 

7> Use the Agent SDK to run Claude Code programmatically from the CLI, Python, or TypeScript.7> Use the Agent SDK to run Claude Code programmatically from the CLI, Python, or TypeScript.

8 8 

9The [Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) gives you the same tools, agent loop, and context management that power Claude Code. It's available as a CLI for scripts and CI/CD, or as [Python](https://platform.claude.com/docs/en/agent-sdk/python) and [TypeScript](https://platform.claude.com/docs/en/agent-sdk/typescript) packages for full programmatic control.9The [Agent SDK](/en/agent-sdk/overview) gives you the same tools, agent loop, and context management that power Claude Code. It's available as a CLI for scripts and CI/CD, or as [Python](/en/agent-sdk/python) and [TypeScript](/en/agent-sdk/typescript) packages for full programmatic control.

10 10 

11<Note>11<Note>

12 The CLI was previously called "headless mode." The `-p` flag and all CLI options work the same way.12 The CLI was previously called "headless mode." The `-p` flag and all CLI options work the same way.


18claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"18claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"

19```19```

20 20 

21This page covers using the Agent SDK via the CLI (`claude -p`). For the Python and TypeScript SDK packages with structured outputs, tool approval callbacks, and native message objects, see the [full Agent SDK documentation](https://platform.claude.com/docs/en/agent-sdk/overview).21This page covers using the Agent SDK via the CLI (`claude -p`). For the Python and TypeScript SDK packages with structured outputs, tool approval callbacks, and native message objects, see the [full Agent SDK documentation](/en/agent-sdk/overview).

22 22 

23## Basic usage23## Basic usage

24 24 


34claude -p "What does the auth module do?"34claude -p "What does the auth module do?"

35```35```

36 36 

37### Start faster with bare mode

38 

39Add `--bare` to reduce startup time by skipping auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. Without it, `claude -p` loads the same [context](/en/how-claude-code-works#the-context-window) an interactive session would, including anything configured in the working directory or `~/.claude`.

40 

41Bare mode is useful for CI and scripts where you need the same result on every machine. A hook in a teammate's `~/.claude` or an MCP server in the project's `.mcp.json` won't run, because bare mode never reads them. Only flags you pass explicitly take effect.

42 

43This example runs a one-off summarize task in bare mode and pre-approves the Read tool so the call completes without a permission prompt:

44 

45```bash theme={null}

46claude --bare -p "Summarize this file" --allowedTools "Read"

47```

48 

49In bare mode Claude has access to the Bash, file read, and file edit tools. Pass any context you need with a flag:

50 

51| To load | Use |

52| ----------------------- | ------------------------------------------------------- |

53| System prompt additions | `--append-system-prompt`, `--append-system-prompt-file` |

54| Settings | `--settings <file-or-json>` |

55| MCP servers | `--mcp-config <file-or-json>` |

56| Custom agents | `--agents <json>` |

57| A plugin directory | `--plugin-dir <path>` |

58 

59Bare mode skips OAuth and keychain reads. Anthropic authentication must come from `ANTHROPIC_API_KEY` or an `apiKeyHelper` in the JSON passed to `--settings`. Bedrock, Vertex, and Foundry use their usual provider credentials.

60 

61<Note>

62 `--bare` is the recommended mode for scripted and SDK calls, and will become the default for `-p` in a future release.

63</Note>

64 

37## Examples65## Examples

38 66 

39These examples highlight common CLI patterns.67These examples highlight common CLI patterns. For CI and other scripted calls, add [`--bare`](#start-faster-with-bare-mode) so they don't pick up whatever happens to be configured locally.

40 68 

41### Get structured output69### Get structured output

42 70 


92 jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'120 jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'

93```121```

94 122 

95For programmatic streaming with callbacks and message objects, see [Stream responses in real-time](https://platform.claude.com/docs/en/agent-sdk/streaming-output) in the Agent SDK documentation.123When an API request fails with a retryable error, Claude Code emits a `system/api_retry` event before retrying. You can use this to surface retry progress or implement custom backoff logic.

124 

125| Field | Type | Description |

126| ---------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |

127| `type` | `"system"` | message type |

128| `subtype` | `"api_retry"` | identifies this as a retry event |

129| `attempt` | integer | current attempt number, starting at 1 |

130| `max_retries` | integer | total retries permitted |

131| `retry_delay_ms` | integer | milliseconds until the next attempt |

132| `error_status` | integer or null | HTTP status code, or `null` for connection errors with no HTTP response |

133| `error` | string | error category: `authentication_failed`, `billing_error`, `rate_limit`, `invalid_request`, `server_error`, `max_output_tokens`, or `unknown` |

134| `uuid` | string | unique event identifier |

135| `session_id` | string | session the event belongs to |

136 

137The `system/init` event reports session metadata including the model, tools, MCP servers, and loaded plugins. It is the first event in the stream unless [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](/en/env-vars) is set, in which case `plugin_install` events precede it. Use the plugin fields to fail CI when a plugin did not load:

138 

139| Field | Type | Description |

140| --------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

141| `plugins` | array | plugins that loaded successfully, each with `name` and `path` |

142| `plugin_errors` | array | plugin load-time errors such as an unsatisfied dependency version, each with `plugin`, `type`, and `message`. Affected plugins are demoted and absent from `plugins`. The key is omitted when there are no errors |

143 

144When [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](/en/env-vars) is set, Claude Code emits `system/plugin_install` events while marketplace plugins install before the first turn. Use these to surface install progress in your own UI.

145 

146| Field | Type | Description |

147| ------------ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |

148| `type` | `"system"` | message type |

149| `subtype` | `"plugin_install"` | identifies this as a plugin install event |

150| `status` | `"started"`, `"installed"`, `"failed"`, or `"completed"` | `started` and `completed` bracket the overall install; `installed` and `failed` report individual marketplaces |

151| `name` | string, optional | marketplace name, present on `installed` and `failed` |

152| `error` | string, optional | failure message, present on `failed` |

153| `uuid` | string | unique event identifier |

154| `session_id` | string | session the event belongs to |

155 

156For programmatic streaming with callbacks and message objects, see [Stream responses in real-time](/en/agent-sdk/streaming-output) in the Agent SDK documentation.

96 157 

97### Auto-approve tools158### Auto-approve tools

98 159 


103 --allowedTools "Bash,Read,Edit"164 --allowedTools "Bash,Read,Edit"

104```165```

105 166 

167To set a baseline for the whole session instead of listing individual tools, pass a [permission mode](/en/permission-modes). `dontAsk` denies anything not in your `permissions.allow` rules or the [read-only command set](/en/permissions#read-only-commands), which is useful for locked-down CI runs. `acceptEdits` lets Claude write files without prompting and also auto-approves common filesystem commands such as `mkdir`, `touch`, `mv`, and `cp`. Other shell commands and network requests still need an `--allowedTools` entry or a `permissions.allow` rule, otherwise the run aborts when one is attempted:

168 

169```bash theme={null}

170claude -p "Apply the lint fixes" --permission-mode acceptEdits

171```

172 

106### Create a commit173### Create a commit

107 174 

108This example reviews staged changes and creates a commit with an appropriate message:175This example reviews staged changes and creates a commit with an appropriate message:


115The `--allowedTools` flag uses [permission rule syntax](/en/settings#permission-rule-syntax). The trailing ` *` enables prefix matching, so `Bash(git diff *)` allows any command starting with `git diff`. The space before `*` is important: without it, `Bash(git diff*)` would also match `git diff-index`.182The `--allowedTools` flag uses [permission rule syntax](/en/settings#permission-rule-syntax). The trailing ` *` enables prefix matching, so `Bash(git diff *)` allows any command starting with `git diff`. The space before `*` is important: without it, `Bash(git diff*)` would also match `git diff-index`.

116 183 

117<Note>184<Note>

118 User-invoked [skills](/en/skills) like `/commit` and [built-in commands](/en/interactive-mode#built-in-commands) are only available in interactive mode. In `-p` mode, describe the task you want to accomplish instead.185 User-invoked [skills](/en/skills) like `/commit` and [built-in commands](/en/commands) are only available in interactive mode. In `-p` mode, describe the task you want to accomplish instead.

119</Note>186</Note>

120 187 

121### Customize the system prompt188### Customize the system prompt


152 219 

153## Next steps220## Next steps

154 221 

155<CardGroup cols={2}>222* [Agent SDK quickstart](/en/agent-sdk/quickstart): build your first agent with Python or TypeScript

156 <Card title="Agent SDK quickstart" icon="play" href="https://platform.claude.com/docs/en/agent-sdk/quickstart">223* [CLI reference](/en/cli-reference): all CLI flags and options

157 Build your first agent with Python or TypeScript224* [GitHub Actions](/en/github-actions): use the Agent SDK in GitHub workflows

158 </Card>225* [GitLab CI/CD](/en/gitlab-ci-cd): use the Agent SDK in GitLab pipelines

159 

160 <Card title="CLI reference" icon="terminal" href="/en/cli-reference">

161 Explore all CLI flags and options

162 </Card>

163 

164 <Card title="GitHub Actions" icon="github" href="/en/github-actions">

165 Use the Agent SDK in GitHub workflows

166 </Card>

167 

168 <Card title="GitLab CI/CD" icon="gitlab" href="/en/gitlab-ci-cd">

169 Use the Agent SDK in GitLab pipelines

170 </Card>

171</CardGroup>

hooks.md +1310 −150

Details

4 4 

5# Hooks reference5# Hooks reference

6 6 

7> Reference for Claude Code hook events, configuration schema, JSON input/output formats, exit codes, async hooks, prompt hooks, and MCP tool hooks.7> Reference for Claude Code hook events, configuration schema, JSON input/output formats, exit codes, async hooks, HTTP hooks, prompt hooks, and MCP tool hooks.

8 8 

9<Tip>9<Tip>

10 For a quickstart guide with examples, see [Automate workflows with hooks](/en/hooks-guide).10 For a quickstart guide with examples, see [Automate workflows with hooks](/en/hooks-guide).

11</Tip>11</Tip>

12 12 

13Hooks are user-defined shell commands or LLM prompts that execute automatically at specific points in Claude Code's lifecycle. Use this reference to look up event schemas, configuration options, JSON input/output formats, and advanced features like async hooks and MCP tool hooks. If you're setting up hooks for the first time, start with the [guide](/en/hooks-guide) instead.13Hooks are user-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code's lifecycle. Use this reference to look up event schemas, configuration options, JSON input/output formats, and advanced features like async hooks, HTTP hooks, and MCP tool hooks. If you're setting up hooks for the first time, start with the [guide](/en/hooks-guide) instead.

14 14 

15## Hook lifecycle15## Hook lifecycle

16 16 

17Hooks fire at specific points during a Claude Code session. When an event fires and a matcher matches, Claude Code passes JSON context about the event to your hook handler. For command hooks, this arrives on stdin. Your handler can then inspect the input, take action, and optionally return a decision. Some events fire once per session, while others fire repeatedly inside the agentic loop:17Hooks fire at specific points during a Claude Code session. When an event fires and a matcher matches, Claude Code passes JSON context about the event to your hook handler. For command hooks, input arrives on stdin. For HTTP hooks, it arrives as the POST request body. Your handler can then inspect the input, take action, and optionally return a decision. Events fall into three cadences: once per session (`SessionStart`, `SessionEnd`), once per turn (`UserPromptSubmit`, `Stop`, `StopFailure`), and on every tool call inside the agentic loop (`PreToolUse`, `PostToolUse`):

18 18 

19<div style={{maxWidth: "500px", margin: "0 auto"}}>19<div style={{maxWidth: "500px", margin: "0 auto"}}>

20 <Frame>20 <Frame>

21 <img src="https://mintcdn.com/claude-code/z2YM37Ycg6eMbID3/images/hooks-lifecycle.png?fit=max&auto=format&n=z2YM37Ycg6eMbID3&q=85&s=5c25fedbc3db6f8882af50c3cc478c32" alt="Hook lifecycle diagram showing the sequence of hooks from SessionStart through the agentic loop to SessionEnd" data-og-width="8876" width="8876" data-og-height="12492" height="12492" data-path="images/hooks-lifecycle.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/z2YM37Ycg6eMbID3/images/hooks-lifecycle.png?w=280&fit=max&auto=format&n=z2YM37Ycg6eMbID3&q=85&s=62406fcd5d4a189cc8842ee1bd946b84 280w, https://mintcdn.com/claude-code/z2YM37Ycg6eMbID3/images/hooks-lifecycle.png?w=560&fit=max&auto=format&n=z2YM37Ycg6eMbID3&q=85&s=fa3049022a6973c5f974e0f95b28169d 560w, https://mintcdn.com/claude-code/z2YM37Ycg6eMbID3/images/hooks-lifecycle.png?w=840&fit=max&auto=format&n=z2YM37Ycg6eMbID3&q=85&s=bd2890897db61a03160b93d4f972ff8e 840w, https://mintcdn.com/claude-code/z2YM37Ycg6eMbID3/images/hooks-lifecycle.png?w=1100&fit=max&auto=format&n=z2YM37Ycg6eMbID3&q=85&s=7ae8e098340479347135e39df4a13454 1100w, https://mintcdn.com/claude-code/z2YM37Ycg6eMbID3/images/hooks-lifecycle.png?w=1650&fit=max&auto=format&n=z2YM37Ycg6eMbID3&q=85&s=848a8606aab22c2ccaa16b6a18431e32 1650w, https://mintcdn.com/claude-code/z2YM37Ycg6eMbID3/images/hooks-lifecycle.png?w=2500&fit=max&auto=format&n=z2YM37Ycg6eMbID3&q=85&s=f3a9ef7feb61fa8fe362005aa185efbc 2500w" />21 <img src="https://mintcdn.com/claude-code/_SQ1BnFTP0QUrae-/images/hooks-lifecycle.svg?fit=max&auto=format&n=_SQ1BnFTP0QUrae-&q=85&s=75bd3d4bdefd4f08a7d736167243fd78" alt="Hook lifecycle diagram showing SessionStart, then a per-turn loop containing UserPromptSubmit, UserPromptExpansion for slash commands, the nested agentic loop (PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart/Stop, TaskCreated, TaskCompleted), and Stop or StopFailure, followed by TeammateIdle, PreCompact, PostCompact, and SessionEnd, with Elicitation and ElicitationResult nested inside MCP tool execution, PermissionDenied as a side branch from PermissionRequest for auto-mode denials, and WorktreeCreate, WorktreeRemove, Notification, ConfigChange, InstructionsLoaded, CwdChanged, and FileChanged as standalone async events" width="520" height="1228" data-path="images/hooks-lifecycle.svg" />

22 </Frame>22 </Frame>

23</div>23</div>

24 24 

25The table below summarizes when each event fires. The [Hook events](#hook-events) section documents the full input schema and decision control options for each one.25The table below summarizes when each event fires. The [Hook events](#hook-events) section documents the full input schema and decision control options for each one.

26 26 

27| Event | When it fires |27| Event | When it fires |

28| :------------------- | :--------------------------------------------------- |28| :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- |

29| `SessionStart` | When a session begins or resumes |29| `SessionStart` | When a session begins or resumes |

30| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |30| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |

31| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |

31| `PreToolUse` | Before a tool call executes. Can block it |32| `PreToolUse` | Before a tool call executes. Can block it |

32| `PermissionRequest` | When a permission dialog appears |33| `PermissionRequest` | When a permission dialog appears |

34| `PermissionDenied` | When a tool call is denied by the auto mode classifier. Return `{retry: true}` to tell the model it may retry the denied tool call |

33| `PostToolUse` | After a tool call succeeds |35| `PostToolUse` | After a tool call succeeds |

34| `PostToolUseFailure` | After a tool call fails |36| `PostToolUseFailure` | After a tool call fails |

37| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |

35| `Notification` | When Claude Code sends a notification |38| `Notification` | When Claude Code sends a notification |

36| `SubagentStart` | When a subagent is spawned |39| `SubagentStart` | When a subagent is spawned |

37| `SubagentStop` | When a subagent finishes |40| `SubagentStop` | When a subagent finishes |

41| `TaskCreated` | When a task is being created via `TaskCreate` |

42| `TaskCompleted` | When a task is being marked as completed |

38| `Stop` | When Claude finishes responding |43| `Stop` | When Claude finishes responding |

44| `StopFailure` | When the turn ends due to an API error. Output and exit code are ignored |

45| `TeammateIdle` | When an [agent team](/en/agent-teams) teammate is about to go idle |

46| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |

47| `ConfigChange` | When a configuration file changes during a session |

48| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |

49| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |

50| `WorktreeCreate` | When a worktree is being created via `--worktree` or `isolation: "worktree"`. Replaces default git behavior |

51| `WorktreeRemove` | When a worktree is being removed, either at session exit or when a subagent finishes |

39| `PreCompact` | Before context compaction |52| `PreCompact` | Before context compaction |

53| `PostCompact` | After context compaction completes |

54| `Elicitation` | When an MCP server requests user input during a tool call |

55| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |

40| `SessionEnd` | When a session terminates |56| `SessionEnd` | When a session terminates |

41 57 

42### How a hook resolves58### How a hook resolves

43 59 

44To see how these pieces fit together, consider this `PreToolUse` hook that blocks destructive shell commands. The hook runs `block-rm.sh` before every Bash tool call:60To see how these pieces fit together, consider this `PreToolUse` hook that blocks destructive shell commands. The `matcher` narrows to Bash tool calls and the `if` condition narrows further to Bash subcommands matching `rm *`, so `block-rm.sh` only spawns when both filters match:

45 61 

46```json theme={null}62```json theme={null}

47{63{


52 "hooks": [68 "hooks": [

53 {69 {

54 "type": "command",70 "type": "command",

55 "command": ".claude/hooks/block-rm.sh"71 "if": "Bash(rm *)",

72 "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm.sh"

56 }73 }

57 ]74 ]

58 }75 }


61}78}

62```79```

63 80 

64The script reads the JSON input from stdin, extracts the command, and blocks it if it contains `rm -rf`:81The script reads the JSON input from stdin, extracts the command, and returns a `permissionDecision` of `"deny"` if it contains `rm -rf`:

65 82 

66```bash theme={null}83```bash theme={null}

67#!/bin/bash84#!/bin/bash


69COMMAND=$(jq -r '.tool_input.command')86COMMAND=$(jq -r '.tool_input.command')

70 87 

71if echo "$COMMAND" | grep -q 'rm -rf'; then88if echo "$COMMAND" | grep -q 'rm -rf'; then

72 echo '{"decision":"block","reason":"Destructive command blocked by hook"}'89 jq -n '{

90 hookSpecificOutput: {

91 hookEventName: "PreToolUse",

92 permissionDecision: "deny",

93 permissionDecisionReason: "Destructive command blocked by hook"

94 }

95 }'

73else96else

74 exit 0 # allow the command97 exit 0 # allow the command

75fi98fi


78Now suppose Claude Code decides to run `Bash "rm -rf /tmp/build"`. Here's what happens:101Now suppose Claude Code decides to run `Bash "rm -rf /tmp/build"`. Here's what happens:

79 102 

80<Frame>103<Frame>

81 <img src="https://mintcdn.com/claude-code/s7NM0vfd_wres2nf/images/hook-resolution.svg?fit=max&auto=format&n=s7NM0vfd_wres2nf&q=85&s=7c13f51ffcbc37d22a593b27e2f2de72" alt="Hook resolution flow: PreToolUse event fires, matcher checks for Bash match, hook handler runs, result returns to Claude Code" data-og-width="780" width="780" data-og-height="290" height="290" data-path="images/hook-resolution.svg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/s7NM0vfd_wres2nf/images/hook-resolution.svg?w=280&fit=max&auto=format&n=s7NM0vfd_wres2nf&q=85&s=36a39a07e8bc1995dcb4639e09846905 280w, https://mintcdn.com/claude-code/s7NM0vfd_wres2nf/images/hook-resolution.svg?w=560&fit=max&auto=format&n=s7NM0vfd_wres2nf&q=85&s=6568d90c596c7605bbac2c325b0a0c86 560w, https://mintcdn.com/claude-code/s7NM0vfd_wres2nf/images/hook-resolution.svg?w=840&fit=max&auto=format&n=s7NM0vfd_wres2nf&q=85&s=255a6f68b9475a0e41dbde7b88002dad 840w, https://mintcdn.com/claude-code/s7NM0vfd_wres2nf/images/hook-resolution.svg?w=1100&fit=max&auto=format&n=s7NM0vfd_wres2nf&q=85&s=dcecf8d5edc88cd2bc49deb006d5760d 1100w, https://mintcdn.com/claude-code/s7NM0vfd_wres2nf/images/hook-resolution.svg?w=1650&fit=max&auto=format&n=s7NM0vfd_wres2nf&q=85&s=04fe51bf69ae375e9fd517f18674e35f 1650w, https://mintcdn.com/claude-code/s7NM0vfd_wres2nf/images/hook-resolution.svg?w=2500&fit=max&auto=format&n=s7NM0vfd_wres2nf&q=85&s=b1b76e0b77fddb5c7fa7bf302dacd80b 2500w" />104 <img src="https://mintcdn.com/claude-code/-tYw1BD_DEqfyyOZ/images/hook-resolution.svg?fit=max&auto=format&n=-tYw1BD_DEqfyyOZ&q=85&s=c73ebc1eeda2037570427d7af1e0a891" alt="Hook resolution flow: PreToolUse event fires, matcher checks for Bash match, if condition checks for Bash(rm *) match, hook handler runs, result returns to Claude Code" width="930" height="290" data-path="images/hook-resolution.svg" />

82</Frame>105</Frame>

83 106 

84<Steps>107<Steps>


91 </Step>114 </Step>

92 115 

93 <Step title="Matcher checks">116 <Step title="Matcher checks">

94 The matcher `"Bash"` matches the tool name, so `block-rm.sh` runs. If you omit the matcher or use `"*"`, the hook runs on every occurrence of the event. Hooks only skip when a matcher is defined and doesn't match.117 The matcher `"Bash"` matches the tool name, so this hook group activates. If you omit the matcher or use `"*"`, the group activates on every occurrence of the event.

118 </Step>

119 

120 <Step title="If condition checks">

121 The `if` condition `"Bash(rm *)"` matches because `rm -rf /tmp/build` is a subcommand matching `rm *`, so this handler spawns. If the command had been `npm test`, the `if` check would fail and `block-rm.sh` would never run, avoiding the process spawn overhead. The `if` field is optional; without it, every handler in the matched group runs.

95 </Step>122 </Step>

96 123 

97 <Step title="Hook handler runs">124 <Step title="Hook handler runs">

98 The script extracts `"rm -rf /tmp/build"` from the input and finds `rm -rf`, so it prints a decision to stdout:125 The script inspects the full command and finds `rm -rf`, so it prints a decision to stdout:

99 126 

100 ```json theme={null}127 ```json theme={null}

101 { "decision": "block", "reason": "Destructive command blocked by hook" }128 {

129 "hookSpecificOutput": {

130 "hookEventName": "PreToolUse",

131 "permissionDecision": "deny",

132 "permissionDecisionReason": "Destructive command blocked by hook"

133 }

134 }

102 ```135 ```

103 136 

104 If the command had been safe (like `npm test`), the script would hit `exit 0` instead, which tells Claude Code to allow the tool call with no further action.137 If the command had been a safer `rm` variant like `rm file.txt`, the script would hit `exit 0` instead, which tells Claude Code to allow the tool call with no further action.

105 </Step>138 </Step>

106 139 

107 <Step title="Claude Code acts on the result">140 <Step title="Claude Code acts on the result">


122See [How a hook resolves](#how-a-hook-resolves) above for a complete walkthrough with an annotated example.155See [How a hook resolves](#how-a-hook-resolves) above for a complete walkthrough with an annotated example.

123 156 

124<Note>157<Note>

125 This page uses specific terms for each level: **hook event** for the lifecycle point, **matcher group** for the filter, and **hook handler** for the shell command, prompt, or agent that runs. "Hook" on its own refers to the general feature.158 This page uses specific terms for each level: **hook event** for the lifecycle point, **matcher group** for the filter, and **hook handler** for the shell command, HTTP endpoint, MCP tool, prompt, or agent that runs. "Hook" on its own refers to the general feature.

126</Note>159</Note>

127 160 

128### Hook locations161### Hook locations


138| [Plugin](/en/plugins) `hooks/hooks.json` | When plugin is enabled | Yes, bundled with the plugin |171| [Plugin](/en/plugins) `hooks/hooks.json` | When plugin is enabled | Yes, bundled with the plugin |

139| [Skill](/en/skills) or [agent](/en/sub-agents) frontmatter | While the component is active | Yes, defined in the component file |172| [Skill](/en/skills) or [agent](/en/sub-agents) frontmatter | While the component is active | Yes, defined in the component file |

140 173 

141For details on settings file resolution, see [settings](/en/settings). Enterprise administrators can use `allowManagedHooksOnly` to block user, project, and plugin hooks. See [Hook configuration](/en/settings#hook-configuration).174For details on settings file resolution, see [settings](/en/settings). Enterprise administrators can use `allowManagedHooksOnly` to block user, project, and plugin hooks. Hooks from plugins force-enabled in managed settings `enabledPlugins` are exempt, so administrators can distribute vetted hooks through an organization marketplace. See [Hook configuration](/en/settings#hook-configuration).

142 175 

143### Matcher patterns176### Matcher patterns

144 177 

145The `matcher` field is a regex string that filters when hooks fire. Use `"*"`, `""`, or omit `matcher` entirely to match all occurrences. Each event type matches on a different field:178The `matcher` field filters when hooks fire. How a matcher is evaluated depends on the characters it contains:

179 

180| Matcher value | Evaluated as | Example |

181| :---------------------------------- | :---------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |

182| `"*"`, `""`, or omitted | Match all | fires on every occurrence of the event |

183| Only letters, digits, `_`, and `\|` | Exact string, or `\|`-separated list of exact strings | `Bash` matches only the Bash tool; `Edit\|Write` matches either tool exactly |

184| Contains any other character | JavaScript regular expression | `^Notebook` matches any tool starting with Notebook; `mcp__memory__.*` matches every tool from the `memory` server |

185 

186The `FileChanged` event does not follow these rules when building its watch list. See [FileChanged](#filechanged).

187 

188Each event type matches on a different field:

146 189 

147| Event | What the matcher filters | Example matcher values |190| Event | What the matcher filters | Example matcher values |

148| :--------------------------------------------------------------------- | :------------------------ | :----------------------------------------------------------------------------- |191| :------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ |

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

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

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

152| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |195| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |

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

154| `PreCompact` | what triggered compaction | `manual`, `auto` |197| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |

155| `SubagentStop` | agent type | same values as `SubagentStart` |198| `SubagentStop` | agent type | same values as `SubagentStart` |

156| `UserPromptSubmit`, `Stop` | no matcher support | always fires on every occurrence |199| `ConfigChange` | configuration source | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |

157 200| `CwdChanged` | no matcher support | always fires on every directory change |

158The matcher is a regex, so `Edit|Write` matches either tool and `Notebook.*` matches any tool starting with Notebook. The matcher runs against a field from the [JSON input](#hook-input-and-output) that Claude Code sends to your hook on stdin. For tool events, that field is `tool_name`. Each [hook event](#hook-events) section lists the full set of matcher values and the input schema for that event.201| `FileChanged` | literal filenames to watch (see [FileChanged](#filechanged)) | `.envrc\|.env` |

202| `StopFailure` | error type | `rate_limit`, `authentication_failed`, `billing_error`, `invalid_request`, `server_error`, `max_output_tokens`, `unknown` |

203| `InstructionsLoaded` | load reason | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |

204| `UserPromptExpansion` | command name | your skill or command names |

205| `Elicitation` | MCP server name | your configured MCP server names |

206| `ElicitationResult` | MCP server name | same values as `Elicitation` |

207| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove` | no matcher support | always fires on every occurrence |

208 

209The matcher runs against a field from the [JSON input](#hook-input-and-output) that Claude Code sends to your hook on stdin. For tool events, that field is `tool_name`. Each [hook event](#hook-events) section lists the full set of matcher values and the input schema for that event.

159 210 

160This example runs a linting script only when Claude writes or edits a file:211This example runs a linting script only when Claude writes or edits a file:

161 212 


177}228}

178```229```

179 230 

180`UserPromptSubmit` and `Stop` don't support matchers and always fire on every occurrence. If you add a `matcher` field to these events, it is silently ignored.231`UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, and `CwdChanged` don't support matchers and always fire on every occurrence. If you add a `matcher` field to these events, it is silently ignored.

232 

233For tool events, you can filter more narrowly by setting the [`if` field](#common-fields) on individual hook handlers. `if` uses [permission rule syntax](/en/permissions) to match against the tool name and arguments together, so `"Bash(git *)"` runs when any subcommand of the Bash input matches `git *` and `"Edit(*.ts)"` runs only for TypeScript files.

181 234 

182#### Match MCP tools235#### Match MCP tools

183 236 

184[MCP](/en/mcp) server tools appear as regular tools in tool events (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`), so you can match them the same way you match any other tool name.237[MCP](/en/mcp) server tools appear as regular tools in tool events (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied`), so you can match them the same way you match any other tool name.

185 238 

186MCP tools follow the naming pattern `mcp__<server>__<tool>`, for example:239MCP tools follow the naming pattern `mcp__<server>__<tool>`, for example:

187 240 


189* `mcp__filesystem__read_file`: Filesystem server's read file tool242* `mcp__filesystem__read_file`: Filesystem server's read file tool

190* `mcp__github__search_repositories`: GitHub server's search tool243* `mcp__github__search_repositories`: GitHub server's search tool

191 244 

192Use regex patterns to target specific MCP tools or groups of tools:245To match every tool from a server, append `.*` to the server prefix. The `.*` is required: a matcher like `mcp__memory` contains only letters and underscores, so it is compared as an exact string and matches no tool.

193 246 

194* `mcp__memory__.*` matches all tools from the `memory` server247* `mcp__memory__.*` matches all tools from the `memory` server

195* `mcp__.*__write.*` matches any tool containing "write" from any server248* `mcp__.*__write.*` matches any tool whose name starts with `write` from any server

196 249 

197This example logs all memory server operations and validates write operations from any MCP server:250This example logs all memory server operations and validates write operations from any MCP server:

198 251 


225 278 

226### Hook handler fields279### Hook handler fields

227 280 

228Each object in the inner `hooks` array is a hook handler: the shell command, LLM prompt, or agent that runs when the matcher matches. There are three types:281Each object in the inner `hooks` array is a hook handler: the shell command, HTTP endpoint, MCP tool, LLM prompt, or agent that runs when the matcher matches. There are five types:

229 282 

230* **[Command hooks](#command-hook-fields)** (`type: "command"`): run a shell command. Your script receives the event's [JSON input](#hook-input-and-output) on stdin and communicates results back through exit codes and stdout.283* **[Command hooks](#command-hook-fields)** (`type: "command"`): run a shell command. Your script receives the event's [JSON input](#hook-input-and-output) on stdin and communicates results back through exit codes and stdout.

284* **[HTTP hooks](#http-hook-fields)** (`type: "http"`): send the event's JSON input as an HTTP POST request to a URL. The endpoint communicates results back through the response body using the same [JSON output format](#json-output) as command hooks.

285* **[MCP tool hooks](#mcp-tool-hook-fields)** (`type: "mcp_tool"`): call a tool on an already-connected [MCP server](/en/mcp). The tool's text output is treated like command-hook stdout.

231* **[Prompt hooks](#prompt-and-agent-hook-fields)** (`type: "prompt"`): send a prompt to a Claude model for single-turn evaluation. The model returns a yes/no decision as JSON. See [Prompt-based hooks](#prompt-based-hooks).286* **[Prompt hooks](#prompt-and-agent-hook-fields)** (`type: "prompt"`): send a prompt to a Claude model for single-turn evaluation. The model returns a yes/no decision as JSON. See [Prompt-based hooks](#prompt-based-hooks).

232* **[Agent hooks](#prompt-and-agent-hook-fields)** (`type: "agent"`): spawn a subagent that can use tools like Read, Grep, and Glob to verify conditions before returning a decision. See [Agent-based hooks](#agent-based-hooks).287* **[Agent hooks](#prompt-and-agent-hook-fields)** (`type: "agent"`): spawn a subagent that can use tools like Read, Grep, and Glob to verify conditions before returning a decision. Agent hooks are experimental and may change. See [Agent-based hooks](#agent-based-hooks).

233 288 

234#### Common fields289#### Common fields

235 290 

236These fields apply to all hook types:291These fields apply to all hook types:

237 292 

238| Field | Required | Description |293| Field | Required | Description |

239| :-------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |294| :-------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

240| `type` | yes | `"command"`, `"prompt"`, or `"agent"` |295| `type` | yes | `"command"`, `"http"`, `"mcp_tool"`, `"prompt"`, or `"agent"` |

296| `if` | no | Permission rule syntax to filter when this hook runs, such as `"Bash(git *)"` or `"Edit(*.ts)"`. The hook only spawns if the tool call matches the pattern, or if a Bash command is too complex to parse. Only evaluated on tool events: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, and `PermissionDenied`. On other events, a hook with `if` set never runs. Uses the same syntax as [permission rules](/en/permissions) |

241| `timeout` | no | Seconds before canceling. Defaults: 600 for command, 30 for prompt, 60 for agent |297| `timeout` | no | Seconds before canceling. Defaults: 600 for command, 30 for prompt, 60 for agent |

242| `statusMessage` | no | Custom spinner message displayed while the hook runs |298| `statusMessage` | no | Custom spinner message displayed while the hook runs |

243| `once` | no | If `true`, runs only once per session then is removed. Skills only, not agents. See [Hooks in skills and agents](#hooks-in-skills-and-agents) |299| `once` | no | If `true`, runs once per session then is removed. Only honored for hooks declared in [skill frontmatter](#hooks-in-skills-and-agents); ignored in settings files and agent frontmatter |

300 

301The `if` field holds exactly one permission rule. There is no `&&`, `||`, or list syntax for combining rules; to apply multiple conditions, define a separate hook handler for each. For Bash, the rule is matched against each subcommand of the tool input after leading `VAR=value` assignments are stripped, so `if: "Bash(git push *)"` matches both `FOO=bar git push` and `npm test && git push`. The hook runs if any subcommand matches, and always runs when the command is too complex to parse.

244 302 

245#### Command hook fields303#### Command hook fields

246 304 

247In addition to the [common fields](#common-fields), command hooks accept these fields:305In addition to the [common fields](#common-fields), command hooks accept these fields:

248 306 

249| Field | Required | Description |307| Field | Required | Description |

250| :-------- | :------- | :------------------------------------------------------------------------------------------------------------------ |308| :------------ | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

251| `command` | yes | Shell command to execute |309| `command` | yes | Shell command to execute |

252| `async` | no | If `true`, runs in the background without blocking. See [Run hooks in the background](#run-hooks-in-the-background) |310| `async` | no | If `true`, runs in the background without blocking. See [Run hooks in the background](#run-hooks-in-the-background) |

311| `asyncRewake` | no | If `true`, runs in the background and wakes Claude on exit code 2. Implies `async`. The hook's stderr, or stdout if stderr is empty, is shown to Claude as a system reminder so it can react to a long-running background failure |

312| `shell` | no | Shell to use for this hook. Accepts `"bash"` (default) or `"powershell"`. Setting `"powershell"` runs the command via PowerShell on Windows. Does not require `CLAUDE_CODE_USE_POWERSHELL_TOOL` since hooks spawn PowerShell directly |

313 

314#### HTTP hook fields

315 

316In addition to the [common fields](#common-fields), HTTP hooks accept these fields:

317 

318| Field | Required | Description |

319| :--------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

320| `url` | yes | URL to send the POST request to |

321| `headers` | no | Additional HTTP headers as key-value pairs. Values support environment variable interpolation using `$VAR_NAME` or `${VAR_NAME}` syntax. Only variables listed in `allowedEnvVars` are resolved |

322| `allowedEnvVars` | no | List of environment variable names that may be interpolated into header values. References to unlisted variables are replaced with empty strings. Required for any env var interpolation to work |

323 

324Claude Code sends the hook's [JSON input](#hook-input-and-output) as the POST request body with `Content-Type: application/json`. The response body uses the same [JSON output format](#json-output) as command hooks.

325 

326Error handling differs from command hooks: non-2xx responses, connection failures, and timeouts all produce non-blocking errors that allow execution to continue. To block a tool call or deny a permission, return a 2xx response with a JSON body containing `decision: "block"` or a `hookSpecificOutput` with `permissionDecision: "deny"`.

327 

328This example sends `PreToolUse` events to a local validation service, authenticating with a token from the `MY_TOKEN` environment variable:

329 

330```json theme={null}

331{

332 "hooks": {

333 "PreToolUse": [

334 {

335 "matcher": "Bash",

336 "hooks": [

337 {

338 "type": "http",

339 "url": "http://localhost:8080/hooks/pre-tool-use",

340 "timeout": 30,

341 "headers": {

342 "Authorization": "Bearer $MY_TOKEN"

343 },

344 "allowedEnvVars": ["MY_TOKEN"]

345 }

346 ]

347 }

348 ]

349 }

350}

351```

352 

353#### MCP tool hook fields

354 

355In addition to the [common fields](#common-fields), MCP tool hooks accept these fields:

356 

357| Field | Required | Description |

358| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

359| `server` | yes | Name of a configured MCP server. The server must already be connected; the hook never triggers an OAuth or connection flow |

360| `tool` | yes | Name of the tool to call on that server |

361| `input` | no | Arguments passed to the tool. String values support `${path}` substitution from the hook's [JSON input](#hook-input-and-output), such as `"${tool_input.file_path}"` |

362 

363The tool's text content is treated like command-hook stdout: if it parses as valid [JSON output](#json-output) it is processed as a decision, otherwise it is shown as plain text. If the named server is not connected, or the tool returns `isError: true`, the hook produces a non-blocking error and execution continues.

364 

365MCP tool hooks are available on every hook event once Claude Code has connected to your MCP servers. `SessionStart` and `Setup` typically fire before servers finish connecting, so hooks on those events should expect the "not connected" error on first run.

366 

367This example calls the `security_scan` tool on the `my_server` MCP server after each `Write` or `Edit`, passing the edited file's path:

368 

369```json theme={null}

370{

371 "hooks": {

372 "PostToolUse": [

373 {

374 "matcher": "Write|Edit",

375 "hooks": [

376 {

377 "type": "mcp_tool",

378 "server": "my_server",

379 "tool": "security_scan",

380 "input": { "file_path": "${tool_input.file_path}" }

381 }

382 ]

383 }

384 ]

385 }

386}

387```

253 388 

254#### Prompt and agent hook fields389#### Prompt and agent hook fields

255 390 


260| `prompt` | yes | Prompt text to send to the model. Use `$ARGUMENTS` as a placeholder for the hook input JSON |395| `prompt` | yes | Prompt text to send to the model. Use `$ARGUMENTS` as a placeholder for the hook input JSON |

261| `model` | no | Model to use for evaluation. Defaults to a fast model |396| `model` | no | Model to use for evaluation. Defaults to a fast model |

262 397 

263All matching hooks run in parallel, and identical handlers are deduplicated automatically. Handlers run in the current directory with Claude Code's environment. The `$CLAUDE_CODE_REMOTE` environment variable is set to `"true"` in remote web environments and not set in the local CLI.398All matching hooks run in parallel, and identical handlers are deduplicated automatically. Command hooks are deduplicated by command string, and HTTP hooks are deduplicated by URL. Handlers run in the current directory with Claude Code's environment. The `$CLAUDE_CODE_REMOTE` environment variable is set to `"true"` in remote web environments and not set in the local CLI.

264 399 

265### Reference scripts by path400### Reference scripts by path

266 401 

267Use environment variables to reference hook scripts relative to the project or plugin root, regardless of the working directory when the hook runs:402Use environment variables to reference hook scripts relative to the project or plugin root, regardless of the working directory when the hook runs:

268 403 

269* `$CLAUDE_PROJECT_DIR`: the project root. Wrap in quotes to handle paths with spaces.404* `$CLAUDE_PROJECT_DIR`: the project root. Wrap in quotes to handle paths with spaces.

270* `${CLAUDE_PLUGIN_ROOT}`: the plugin's root directory, for scripts bundled with a [plugin](/en/plugins).405* `${CLAUDE_PLUGIN_ROOT}`: the plugin's installation directory, for scripts bundled with a [plugin](/en/plugins). Changes on each plugin update.

406* `${CLAUDE_PLUGIN_DATA}`: the plugin's [persistent data directory](/en/plugins-reference#persistent-data-directory), for dependencies and state that should survive plugin updates.

271 407 

272<Tabs>408<Tabs>

273 <Tab title="Project scripts">409 <Tab title="Project scripts">


348 484 

349### The `/hooks` menu485### The `/hooks` menu

350 486 

351Type `/hooks` in Claude Code to open the interactive hooks manager, where you can view, add, and delete hooks without editing settings files directly. For a step-by-step walkthrough, see [Set up your first hook](/en/hooks-guide#set-up-your-first-hook) in the guide.487Type `/hooks` in Claude Code to open a read-only browser for your configured hooks. The menu shows every hook event with a count of configured hooks, lets you drill into matchers, and shows the full details of each hook handler. Use it to verify configuration, check which settings file a hook came from, or inspect a hook's command, prompt, or URL.

352 488 

353Each hook in the menu is labeled with a bracket prefix indicating its source:489The menu displays all five hook types: `command`, `prompt`, `agent`, `http`, and `mcp_tool`. Each hook is labeled with a `[type]` prefix and a source indicating where it was defined:

354 490 

355* `[User]`: from `~/.claude/settings.json`491* `User`: from `~/.claude/settings.json`

356* `[Project]`: from `.claude/settings.json`492* `Project`: from `.claude/settings.json`

357* `[Local]`: from `.claude/settings.local.json`493* `Local`: from `.claude/settings.local.json`

358* `[Plugin]`: from a plugin's `hooks/hooks.json`, read-only494* `Plugin`: from a plugin's `hooks/hooks.json`

495* `Session`: registered in memory for the current session

496* `Built-in`: registered internally by Claude Code

497 

498Selecting a hook opens a detail view showing its event, matcher, type, source file, and the full command, prompt, or URL. The menu is read-only: to add, modify, or remove hooks, edit the settings JSON directly or ask Claude to make the change.

359 499 

360### Disable or remove hooks500### Disable or remove hooks

361 501 

362To remove a hook, delete its entry from the settings JSON file, or use the `/hooks` menu and select the hook to delete it.502To remove a hook, delete its entry from the settings JSON file.

503 

504To temporarily disable all hooks without removing them, set `"disableAllHooks": true` in your settings file. There is no way to disable an individual hook while keeping it in the configuration.

363 505 

364To temporarily disable all hooks without removing them, set `"disableAllHooks": true` in your settings file or use the toggle in the `/hooks` menu. There is no way to disable an individual hook while keeping it in the configuration.506The `disableAllHooks` setting respects the managed settings hierarchy. If an administrator has configured hooks through managed policy settings, `disableAllHooks` set in user, project, or local settings cannot disable those managed hooks. Only `disableAllHooks` set at the managed settings level can disable managed hooks.

365 507 

366Direct edits to hooks in settings files don't take effect immediately. Claude Code captures a snapshot of hooks at startup and uses it throughout the session. This prevents malicious or accidental hook modifications from taking effect mid-session without your review. If hooks are modified externally, Claude Code warns you and requires review in the `/hooks` menu before changes apply.508Direct edits to hooks in settings files are normally picked up automatically by the file watcher.

367 509 

368## Hook input and output510## Hook input and output

369 511 

370Hooks receive JSON data via stdin and communicate results through exit codes, stdout, and stderr. This section covers fields and behavior common to all events. Each event's section under [Hook events](#hook-events) includes its specific input schema and decision control options.512Command hooks receive JSON data via stdin and communicate results through exit codes, stdout, and stderr. HTTP hooks receive the same JSON as the POST request body and communicate results through the HTTP response body. This section covers fields and behavior common to all events. Each event's section under [Hook events](#hook-events) includes its specific input schema and decision control options.

371 513 

372### Common input fields514### Common input fields

373 515 

374All hook events receive these fields via stdin as JSON, in addition to event-specific fields documented in each [hook event](#hook-events) section:516Hook events receive these fields as JSON, in addition to event-specific fields documented in each [hook event](#hook-events) section. For command hooks, this JSON arrives via stdin. For HTTP hooks, it arrives as the POST request body.

375 517 

376| Field | Description |518| Field | Description |

377| :---------------- | :--------------------------------------------------------------------------------------------------------------------------------- |519| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

378| `session_id` | Current session identifier |520| `session_id` | Current session identifier |

379| `transcript_path` | Path to conversation JSON |521| `transcript_path` | Path to conversation JSON |

380| `cwd` | Current working directory when the hook is invoked |522| `cwd` | Current working directory when the hook is invoked |

381| `permission_mode` | Current [permission mode](/en/iam#permission-modes): `"default"`, `"plan"`, `"acceptEdits"`, `"dontAsk"`, or `"bypassPermissions"` |523| `permission_mode` | Current [permission mode](/en/permissions#permission-modes): `"default"`, `"plan"`, `"acceptEdits"`, `"auto"`, `"dontAsk"`, or `"bypassPermissions"`. Not all events receive this field: see each event's JSON example below to check |

382| `hook_event_name` | Name of the event that fired |524| `hook_event_name` | Name of the event that fired |

383 525 

526When running with `--agent` or inside a subagent, two additional fields are included:

527 

528| Field | Description |

529| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

530| `agent_id` | Unique identifier for the subagent. Present only when the hook fires inside a subagent call. Use this to distinguish subagent hook calls from main-thread calls. |

531| `agent_type` | Agent name (for example, `"Explore"` or `"security-reviewer"`). Present when the session uses `--agent` or the hook fires inside a subagent. For subagents, the subagent's type takes precedence over the session's `--agent` value. |

532 

384For example, a `PreToolUse` hook for a Bash command receives this on stdin:533For example, a `PreToolUse` hook for a Bash command receives this on stdin:

385 534 

386```json theme={null}535```json theme={null}


403 552 

404The exit code from your hook command tells Claude Code whether the action should proceed, be blocked, or be ignored.553The exit code from your hook command tells Claude Code whether the action should proceed, be blocked, or be ignored.

405 554 

406**Exit 0** means success. Claude Code parses stdout for [JSON output fields](#json-output) like `decision` or `reason`. JSON output is only processed on exit 0. For most events, stdout is only shown in verbose mode (`Ctrl+O`). The exceptions are `UserPromptSubmit` and `SessionStart`, where stdout is added as context that Claude can see and act on.555**Exit 0** means success. Claude Code parses stdout for [JSON output fields](#json-output). JSON output is only processed on exit 0. For most events, stdout is written to the debug log but not shown in the transcript. The exceptions are `UserPromptSubmit`, `UserPromptExpansion`, and `SessionStart`, where stdout is added as context that Claude can see and act on.

407 556 

408**Exit 2** means a blocking error. Claude Code ignores stdout and any JSON in it. Instead, stderr text is fed back to Claude as an error message. The effect depends on the event: `PreToolUse` blocks the tool call, `UserPromptSubmit` rejects the prompt, and so on. See [exit code 2 behavior](#exit-code-2-behavior-per-event) for the full list.557**Exit 2** means a blocking error. Claude Code ignores stdout and any JSON in it. Instead, stderr text is fed back to Claude as an error message. The effect depends on the event: `PreToolUse` blocks the tool call, `UserPromptSubmit` rejects the prompt, and so on. See [exit code 2 behavior](#exit-code-2-behavior-per-event) for the full list.

409 558 

410**Any other exit code** is a non-blocking error. stderr is shown in verbose mode (`Ctrl+O`) and execution continues.559**Any other exit code** is a non-blocking error for most hook events. The transcript shows a `<hook name> hook error` notice followed by the first line of stderr, so you can identify the cause without `--debug`. Execution continues and the full stderr is written to the debug log.

411 560 

412For example, a hook command script that blocks dangerous Bash commands:561For example, a hook command script that blocks dangerous Bash commands:

413 562 


424exit 0 # Success: tool call proceeds573exit 0 # Success: tool call proceeds

425```574```

426 575 

576<Warning>

577 For most hook events, only exit code 2 blocks the action. Claude Code treats exit code 1 as a non-blocking error and proceeds with the action, even though 1 is the conventional Unix failure code. If your hook is meant to enforce a policy, use `exit 2`. The exception is `WorktreeCreate`, where any non-zero exit code aborts worktree creation.

578</Warning>

579 

427#### Exit code 2 behavior per event580#### Exit code 2 behavior per event

428 581 

429Exit code 2 is the way a hook signals "stop, don't do this." The effect depends on the event, because some events represent actions that can be blocked (like a tool call that hasn't happened yet) and others represent things that already happened or can't be prevented.582Exit code 2 is the way a hook signals "stop, don't do this." The effect depends on the event, because some events represent actions that can be blocked (like a tool call that hasn't happened yet) and others represent things that already happened or can't be prevented.

430 583 

431| Hook event | Can block? | What happens on exit 2 |584| Hook event | Can block? | What happens on exit 2 |

432| :------------------- | :--------- | :-------------------------------------------------------- |585| :-------------------- | :--------- | :----------------------------------------------------------------------------------------------------------------------------------- |

433| `PreToolUse` | Yes | Blocks the tool call |586| `PreToolUse` | Yes | Blocks the tool call |

434| `PermissionRequest` | Yes | Denies the permission |587| `PermissionRequest` | Yes | Denies the permission |

435| `UserPromptSubmit` | Yes | Blocks prompt processing and erases the prompt |588| `UserPromptSubmit` | Yes | Blocks prompt processing and erases the prompt |

589| `UserPromptExpansion` | Yes | Blocks the expansion |

436| `Stop` | Yes | Prevents Claude from stopping, continues the conversation |590| `Stop` | Yes | Prevents Claude from stopping, continues the conversation |

437| `SubagentStop` | Yes | Prevents the subagent from stopping |591| `SubagentStop` | Yes | Prevents the subagent from stopping |

592| `TeammateIdle` | Yes | Prevents the teammate from going idle (teammate continues working) |

593| `TaskCreated` | Yes | Rolls back the task creation |

594| `TaskCompleted` | Yes | Prevents the task from being marked as completed |

595| `ConfigChange` | Yes | Blocks the configuration change from taking effect (except `policy_settings`) |

596| `StopFailure` | No | Output and exit code are ignored |

438| `PostToolUse` | No | Shows stderr to Claude (tool already ran) |597| `PostToolUse` | No | Shows stderr to Claude (tool already ran) |

439| `PostToolUseFailure` | No | Shows stderr to Claude (tool already failed) |598| `PostToolUseFailure` | No | Shows stderr to Claude (tool already failed) |

599| `PostToolBatch` | Yes | Stops the agentic loop before the next model call |

600| `PermissionDenied` | No | Exit code and stderr are ignored (denial already occurred). Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry |

440| `Notification` | No | Shows stderr to user only |601| `Notification` | No | Shows stderr to user only |

441| `SubagentStart` | No | Shows stderr to user only |602| `SubagentStart` | No | Shows stderr to user only |

442| `SessionStart` | No | Shows stderr to user only |603| `SessionStart` | No | Shows stderr to user only |

443| `SessionEnd` | No | Shows stderr to user only |604| `SessionEnd` | No | Shows stderr to user only |

444| `PreCompact` | No | Shows stderr to user only |605| `CwdChanged` | No | Shows stderr to user only |

606| `FileChanged` | No | Shows stderr to user only |

607| `PreCompact` | Yes | Blocks compaction |

608| `PostCompact` | No | Shows stderr to user only |

609| `Elicitation` | Yes | Denies the elicitation |

610| `ElicitationResult` | Yes | Blocks the response (action becomes decline) |

611| `WorktreeCreate` | Yes | Any non-zero exit code causes worktree creation to fail |

612| `WorktreeRemove` | No | Failures are logged in debug mode only |

613| `InstructionsLoaded` | No | Exit code is ignored |

614 

615### HTTP response handling

616 

617HTTP hooks use HTTP status codes and response bodies instead of exit codes and stdout:

618 

619* **2xx with an empty body**: success, equivalent to exit code 0 with no output

620* **2xx with a plain text body**: success, the text is added as context

621* **2xx with a JSON body**: success, parsed using the same [JSON output](#json-output) schema as command hooks

622* **Non-2xx status**: non-blocking error, execution continues

623* **Connection failure or timeout**: non-blocking error, execution continues

624 

625Unlike command hooks, HTTP hooks cannot signal a blocking error through status codes alone. To block a tool call or deny a permission, return a 2xx response with a JSON body containing the appropriate decision fields.

445 626 

446### JSON output627### JSON output

447 628 

448You must choose one approach per hook, not both: either use exit codes alone for signaling, or exit 0 and print JSON for structured control. Claude Code only processes JSON on exit 0. If you exit 2, any JSON is ignored.629Exit codes let you allow or block, but JSON output gives you finer-grained control. Instead of exiting with code 2 to block, exit 0 and print a JSON object to stdout. Claude Code reads specific fields from that JSON to control behavior, including [decision control](#decision-control) for blocking, allowing, or escalating to the user.

449 630 

450Instead of relying on exit codes alone, hooks can print JSON to stdout on exit 0. Claude Code reads specific fields from this JSON to decide what to do next.631<Note>

632 You must choose one approach per hook, not both: either use exit codes alone for signaling, or exit 0 and print JSON for structured control. Claude Code only processes JSON on exit 0. If you exit 2, any JSON is ignored.

633</Note>

451 634 

452Your hook's stdout must contain only the JSON object. If your shell profile prints text on startup, it can interfere with JSON parsing. See [JSON validation failed](/en/hooks-guide#json-validation-failed) in the troubleshooting guide.635Your hook's stdout must contain only the JSON object. If your shell profile prints text on startup, it can interfere with JSON parsing. See [JSON validation failed](/en/hooks-guide#json-validation-failed) in the troubleshooting guide.

453 636 

454The JSON object has two parts:637Hook output injected into context (`additionalContext`, `systemMessage`, or plain stdout) is capped at 10,000 characters. Output that exceeds this limit is saved to a file and replaced with a preview and file path, the same way large tool results are handled.

455 638 

456* **Top-level fields** like `continue` and `decision` work across all events. These are listed in the table below.639The JSON object supports three kinds of fields:

457* **`hookSpecificOutput`** is a nested object for event-specific fields like `permissionDecision` or `additionalContext`. It requires a `hookEventName` field set to the event name, like `"PreToolUse"` or `"Stop"`. Each event's decision control section under [Hook events](#hook-events) documents what fields go here.640 

641* **Universal fields** like `continue` work across all events. These are listed in the table below.

642* **Top-level `decision` and `reason`** are used by some events to block or provide feedback.

643* **`hookSpecificOutput`** is a nested object for events that need richer control. It requires a `hookEventName` field set to the event name.

458 644 

459| Field | Default | Description |645| Field | Default | Description |

460| :--------------- | :------ | :---------------------------------------------------------------------------------------------------------------------------------------------------- |646| :--------------- | :------ | :------------------------------------------------------------------------------------------------------------------------- |

461| `continue` | `true` | If `false`, Claude stops processing entirely after the hook runs. Takes precedence over event-specific fields like `decision` or `permissionDecision` |647| `continue` | `true` | If `false`, Claude stops processing entirely after the hook runs. Takes precedence over any event-specific decision fields |

462| `stopReason` | none | Message shown to the user when `continue` is `false`. Not shown to Claude |648| `stopReason` | none | Message shown to the user when `continue` is `false`. Not shown to Claude |

463| `suppressOutput` | `false` | If `true`, hides stdout from verbose mode output |649| `suppressOutput` | `false` | If `true`, omits stdout from the debug log |

464| `systemMessage` | none | Warning message shown to the user |650| `systemMessage` | none | Warning message shown to the user |

465 651 

466This example uses a top-level field to stop Claude:652To stop Claude entirely regardless of event type:

467 653 

468```json theme={null}654```json theme={null}

469{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }655{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }

470```656```

471 657 

472This example uses `hookSpecificOutput` to deny a PreToolUse tool call:658#### Decision control

473 659 

474```json theme={null}660Not every event supports blocking or controlling behavior through JSON. The events that do each use a different set of fields to express that decision. Use this table as a quick reference before writing a hook:

475{661 

662| Events | Decision pattern | Key fields |

663| :---------------------------------------------------------------------------------------------------------------------------------- | :----------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

664| UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact | Top-level `decision` | `decision: "block"`, `reason` |

665| TeammateIdle, TaskCreated, TaskCompleted | Exit code or `continue: false` | Exit code 2 blocks the action with stderr feedback. JSON `{"continue": false, "stopReason": "..."}` also stops the teammate entirely, matching `Stop` hook behavior |

666| PreToolUse | `hookSpecificOutput` | `permissionDecision` (allow/deny/ask/defer), `permissionDecisionReason` |

667| PermissionRequest | `hookSpecificOutput` | `decision.behavior` (allow/deny) |

668| PermissionDenied | `hookSpecificOutput` | `retry: true` tells the model it may retry the denied tool call |

669| WorktreeCreate | path return | Command hook prints path on stdout; HTTP hook returns `hookSpecificOutput.worktreePath`. Hook failure or missing path fails creation |

670| Elicitation | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (form field values for accept) |

671| ElicitationResult | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (form field values override) |

672| WorktreeRemove, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, FileChanged | None | No decision control. Used for side effects like logging or cleanup |

673 

674Here are examples of each pattern in action:

675 

676<Tabs>

677 <Tab title="Top-level decision">

678 Used by `UserPromptSubmit`, `UserPromptExpansion`, `PostToolUse`, `PostToolUseFailure`, `PostToolBatch`, `Stop`, `SubagentStop`, `ConfigChange`, and `PreCompact`. The only value is `"block"`. To allow the action to proceed, omit `decision` from your JSON, or exit 0 without any JSON at all:

679 

680 ```json theme={null}

681 {

682 "decision": "block",

683 "reason": "Test suite must pass before proceeding"

684 }

685 ```

686 </Tab>

687 

688 <Tab title="PreToolUse">

689 Uses `hookSpecificOutput` for richer control: allow, deny, or escalate to the user. You can also modify tool input before it runs or inject additional context for Claude. See [PreToolUse decision control](#pretooluse-decision-control) for the full set of options.

690 

691 ```json theme={null}

692 {

476 "hookSpecificOutput": {693 "hookSpecificOutput": {

477 "hookEventName": "PreToolUse",694 "hookEventName": "PreToolUse",

478 "permissionDecision": "deny",695 "permissionDecision": "deny",

479 "permissionDecisionReason": "Database writes are not allowed"696 "permissionDecisionReason": "Database writes are not allowed"

480 }697 }

481}698 }

482```699 ```

700 </Tab>

701 

702 <Tab title="PermissionRequest">

703 Uses `hookSpecificOutput` to allow or deny a permission request on behalf of the user. When allowing, you can also modify the tool's input or apply permission rules so the user isn't prompted again. See [PermissionRequest decision control](#permissionrequest-decision-control) for the full set of options.

704 

705 ```json theme={null}

706 {

707 "hookSpecificOutput": {

708 "hookEventName": "PermissionRequest",

709 "decision": {

710 "behavior": "allow",

711 "updatedInput": {

712 "command": "npm run lint"

713 }

714 }

715 }

716 }

717 ```

718 </Tab>

719</Tabs>

483 720 

484For extended examples including Bash command validation, prompt filtering, and auto-approval scripts, see [What you can automate](/en/hooks-guide#what-you-can-automate) in the guide and the [Bash command validator reference implementation](https://github.com/anthropics/claude-code/blob/main/examples/hooks/bash_command_validator_example.py).721For extended examples including Bash command validation, prompt filtering, and auto-approval scripts, see [What you can automate](/en/hooks-guide#what-you-can-automate) in the guide and the [Bash command validator reference implementation](https://github.com/anthropics/claude-code/blob/main/examples/hooks/bash_command_validator_example.py).

485 722 


491 728 

492Runs when Claude Code starts a new session or resumes an existing session. Useful for loading development context like existing issues or recent changes to your codebase, or setting up environment variables. For static context that does not require a script, use [CLAUDE.md](/en/memory) instead.729Runs when Claude Code starts a new session or resumes an existing session. Useful for loading development context like existing issues or recent changes to your codebase, or setting up environment variables. For static context that does not require a script, use [CLAUDE.md](/en/memory) instead.

493 730 

494SessionStart runs on every session, so keep these hooks fast.731SessionStart runs on every session, so keep these hooks fast. Only `type: "command"` and `type: "mcp_tool"` hooks are supported.

495 732 

496The matcher value corresponds to how the session was initiated:733The matcher value corresponds to how the session was initiated:

497 734 


511 "session_id": "abc123",748 "session_id": "abc123",

512 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",749 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

513 "cwd": "/Users/...",750 "cwd": "/Users/...",

514 "permission_mode": "default",

515 "hook_event_name": "SessionStart",751 "hook_event_name": "SessionStart",

516 "source": "startup",752 "source": "startup",

517 "model": "claude-sonnet-4-5-20250929"753 "model": "claude-sonnet-4-6"

518}754}

519```755```

520 756 


575Any variables written to this file will be available in all subsequent Bash commands that Claude Code executes during the session.811Any variables written to this file will be available in all subsequent Bash commands that Claude Code executes during the session.

576 812 

577<Note>813<Note>

578 `CLAUDE_ENV_FILE` is available for SessionStart hooks. Other hook types do not have access to this variable.814 `CLAUDE_ENV_FILE` is available for SessionStart, [CwdChanged](#cwdchanged), and [FileChanged](#filechanged) hooks. Other hook types do not have access to this variable.

579</Note>815</Note>

580 816 

817### InstructionsLoaded

818 

819Fires when a `CLAUDE.md` or `.claude/rules/*.md` file is loaded into context. This event fires at session start for eagerly-loaded files and again later when files are lazily loaded, for example when Claude accesses a subdirectory that contains a nested `CLAUDE.md` or when conditional rules with `paths:` frontmatter match. The hook does not support blocking or decision control. It runs asynchronously for observability purposes.

820 

821The matcher runs against `load_reason`. For example, use `"matcher": "session_start"` to fire only for files loaded at session start, or `"matcher": "path_glob_match|nested_traversal"` to fire only for lazy loads.

822 

823#### InstructionsLoaded input

824 

825In addition to the [common input fields](#common-input-fields), InstructionsLoaded hooks receive these fields:

826 

827| Field | Description |

828| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

829| `file_path` | Absolute path to the instruction file that was loaded |

830| `memory_type` | Scope of the file: `"User"`, `"Project"`, `"Local"`, or `"Managed"` |

831| `load_reason` | Why the file was loaded: `"session_start"`, `"nested_traversal"`, `"path_glob_match"`, `"include"`, or `"compact"`. The `"compact"` value fires when instruction files are re-loaded after a compaction event |

832| `globs` | Path glob patterns from the file's `paths:` frontmatter, if any. Present only for `path_glob_match` loads |

833| `trigger_file_path` | Path to the file whose access triggered this load, for lazy loads |

834| `parent_file_path` | Path to the parent instruction file that included this one, for `include` loads |

835 

836```json theme={null}

837{

838 "session_id": "abc123",

839 "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",

840 "cwd": "/Users/my-project",

841 "hook_event_name": "InstructionsLoaded",

842 "file_path": "/Users/my-project/CLAUDE.md",

843 "memory_type": "Project",

844 "load_reason": "session_start"

845}

846```

847 

848#### InstructionsLoaded decision control

849 

850InstructionsLoaded hooks have no decision control. They cannot block or modify instruction loading. Use this event for audit logging, compliance tracking, or observability.

851 

581### UserPromptSubmit852### UserPromptSubmit

582 853 

583Runs when the user submits a prompt, before Claude processes it. This allows you854Runs when the user submits a prompt, before Claude processes it. This allows you


617| `decision` | `"block"` prevents the prompt from being processed and erases it from context. Omit to allow the prompt to proceed |888| `decision` | `"block"` prevents the prompt from being processed and erases it from context. Omit to allow the prompt to proceed |

618| `reason` | Shown to the user when `decision` is `"block"`. Not added to context |889| `reason` | Shown to the user when `decision` is `"block"`. Not added to context |

619| `additionalContext` | String added to Claude's context |890| `additionalContext` | String added to Claude's context |

891| `sessionTitle` | Sets the session title, same effect as `/rename`. Use to name sessions automatically based on the prompt content |

620 892 

621```json theme={null}893```json theme={null}

622{894{


624 "reason": "Explanation for decision",896 "reason": "Explanation for decision",

625 "hookSpecificOutput": {897 "hookSpecificOutput": {

626 "hookEventName": "UserPromptSubmit",898 "hookEventName": "UserPromptSubmit",

627 "additionalContext": "My additional context here"899 "additionalContext": "My additional context here",

900 "sessionTitle": "My session title"

628 }901 }

629}902}

630```903```


634 block prompts or want more structured control.907 block prompts or want more structured control.

635</Note>908</Note>

636 909 

910### UserPromptExpansion

911 

912Runs when a user-typed slash command expands into a prompt before reaching Claude. Use this to block specific commands from direct invocation, inject context for a particular skill, or log which commands users invoke. For example, a hook matching `deploy` can block `/deploy` unless an approval file is present, or a hook matching a review skill can append the team's review checklist as `additionalContext`.

913 

914This event covers the path `PreToolUse` does not: a `PreToolUse` hook matching the `Skill` tool fires only when Claude calls the tool, but typing `/skillname` directly bypasses `PreToolUse`. `UserPromptExpansion` fires on that direct path.

915 

916Matches on `command_name`. Leave the matcher empty to fire on every prompt-type slash command.

917 

918#### UserPromptExpansion input

919 

920In addition to the [common input fields](#common-input-fields), UserPromptExpansion hooks receive `expansion_type`, `command_name`, `command_args`, `command_source`, and the original `prompt` string. The `expansion_type` field is `slash_command` for skill and custom commands, or `mcp_prompt` for MCP server prompts.

921 

922```json theme={null}

923{

924 "session_id": "abc123",

925 "transcript_path": "/Users/.../00893aaf.jsonl",

926 "cwd": "/Users/...",

927 "permission_mode": "default",

928 "hook_event_name": "UserPromptExpansion",

929 "expansion_type": "slash_command",

930 "command_name": "example-skill",

931 "command_args": "arg1 arg2",

932 "command_source": "plugin",

933 "prompt": "/example-skill arg1 arg2"

934}

935```

936 

937#### UserPromptExpansion decision control

938 

939`UserPromptExpansion` hooks can block the expansion or add context. All [JSON output fields](#json-output) are available.

940 

941| Field | Description |

942| :------------------ | :------------------------------------------------------------------------------- |

943| `decision` | `"block"` prevents the slash command from expanding. Omit to allow it to proceed |

944| `reason` | Shown to the user when `decision` is `"block"` |

945| `additionalContext` | String added to Claude's context alongside the expanded prompt |

946 

947```json theme={null}

948{

949 "decision": "block",

950 "reason": "This slash command is not available",

951 "hookSpecificOutput": {

952 "hookEventName": "UserPromptExpansion",

953 "additionalContext": "Additional context for this expansion"

954 }

955}

956```

957 

637### PreToolUse958### PreToolUse

638 959 

639Runs after Claude creates tool parameters and before processing the tool call. Matches on tool name: `Bash`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Task`, `WebFetch`, `WebSearch`, and any [MCP tool names](#match-mcp-tools).960Runs after Claude creates tool parameters and before processing the tool call. Matches on tool name: `Bash`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Agent`, `WebFetch`, `WebSearch`, `AskUserQuestion`, `ExitPlanMode`, and any [MCP tool names](#match-mcp-tools).

640 961 

641Use [PreToolUse decision control](#pretooluse-decision-control) to allow, deny, or ask for permission to use the tool.962Use [PreToolUse decision control](#pretooluse-decision-control) to allow, deny, ask, or defer the tool call.

642 963 

643#### PreToolUse input964#### PreToolUse input

644 965 


726| `allowed_domains` | array | `["docs.example.com"]` | Optional: only include results from these domains |1047| `allowed_domains` | array | `["docs.example.com"]` | Optional: only include results from these domains |

727| `blocked_domains` | array | `["spam.example.com"]` | Optional: exclude results from these domains |1048| `blocked_domains` | array | `["spam.example.com"]` | Optional: exclude results from these domains |

728 1049 

729##### Task1050##### Agent

730 1051 

731Spawns a [subagent](/en/sub-agents).1052Spawns a [subagent](/en/sub-agents).

732 1053 


737| `subagent_type` | string | `"Explore"` | Type of specialized agent to use |1058| `subagent_type` | string | `"Explore"` | Type of specialized agent to use |

738| `model` | string | `"sonnet"` | Optional model alias to override the default |1059| `model` | string | `"sonnet"` | Optional model alias to override the default |

739 1060 

1061##### AskUserQuestion

1062 

1063Asks the user one to four multiple-choice questions.

1064 

1065| Field | Type | Example | Description |

1066| :---------- | :----- | :----------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

1067| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | Questions to present, each with a `question` string, short `header`, `options` array, and optional `multiSelect` flag |

1068| `answers` | object | `{"Which framework?": "React"}` | Optional. Maps question text to the selected option label. Multi-select answers join labels with commas. Claude does not set this field; supply it via `updatedInput` to answer programmatically |

1069 

740#### PreToolUse decision control1070#### PreToolUse decision control

741 1071 

742`PreToolUse` hooks can control whether a tool call proceeds. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return a `hookSpecificOutput` object with these event-specific fields:1072`PreToolUse` hooks can control whether a tool call proceeds. Unlike other hooks that use a top-level `decision` field, PreToolUse returns its decision inside a `hookSpecificOutput` object. This gives it richer control: four outcomes (allow, deny, ask, or defer) plus the ability to modify tool input before execution.

743 1073 

744| Field | Description |1074| Field | Description |

745| :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- |1075| :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

746| `permissionDecision` | `"allow"` bypasses the permission system, `"deny"` prevents the tool call, `"ask"` prompts the user to confirm |1076| `permissionDecision` | `"allow"` skips the permission prompt. `"deny"` prevents the tool call. `"ask"` prompts the user to confirm. `"defer"` exits gracefully so the tool can be resumed later. [Deny and ask rules](/en/permissions#manage-permissions) are still evaluated regardless of what the hook returns |

747| `permissionDecisionReason` | For `"allow"` and `"ask"`, shown to the user but not Claude. For `"deny"`, shown to Claude |1077| `permissionDecisionReason` | For `"allow"` and `"ask"`, shown to the user but not Claude. For `"deny"`, shown to Claude. For `"defer"`, ignored |

748| `updatedInput` | Modifies the tool's input parameters before execution. Combine with `"allow"` to auto-approve, or `"ask"` to show the modified input to the user |1078| `updatedInput` | Modifies the tool's input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. Combine with `"allow"` to auto-approve, or `"ask"` to show the modified input to the user. For `"defer"`, ignored |

749| `additionalContext` | String added to Claude's context before the tool executes |1079| `additionalContext` | String added to Claude's context before the tool executes. For `"defer"`, ignored |

1080 

1081When multiple PreToolUse hooks return different decisions, precedence is `deny` > `defer` > `ask` > `allow`.

1082 

1083When a hook returns `"ask"`, the permission prompt displayed to the user includes a label identifying where the hook came from: for example, `[User]`, `[Project]`, `[Plugin]`, or `[Local]`. This helps users understand which configuration source is requesting confirmation.

750 1084 

751```json theme={null}1085```json theme={null}

752{1086{


762}1096}

763```1097```

764 1098 

1099`AskUserQuestion` and `ExitPlanMode` require user interaction and normally block in [non-interactive mode](/en/headless) with the `-p` flag. Returning `permissionDecision: "allow"` together with `updatedInput` satisfies that requirement: the hook reads the tool's input from stdin, collects the answer through your own UI, and returns it in `updatedInput` so the tool runs without prompting. Returning `"allow"` alone is not sufficient for these tools. For `AskUserQuestion`, echo back the original `questions` array and add an [`answers`](#askuserquestion) object mapping each question's text to the chosen answer.

1100 

1101<Note>

1102 PreToolUse previously used top-level `decision` and `reason` fields, but these are deprecated for this event. Use `hookSpecificOutput.permissionDecision` and `hookSpecificOutput.permissionDecisionReason` instead. The deprecated values `"approve"` and `"block"` map to `"allow"` and `"deny"` respectively. Other events like PostToolUse and Stop continue to use top-level `decision` and `reason` as their current format.

1103</Note>

1104 

1105#### Defer a tool call for later

1106 

1107`"defer"` is for integrations that run `claude -p` as a subprocess and read its JSON output, such as an Agent SDK app or a custom UI built on top of Claude Code. It lets that calling process pause Claude at a tool call, collect input through its own interface, and resume where it left off. Claude Code honors this value only in [non-interactive mode](/en/headless) with the `-p` flag. In interactive sessions it logs a warning and ignores the hook result.

1108 

765<Note>1109<Note>

766 The `decision` and `reason` fields are deprecated for PreToolUse hooks.1110 The `defer` value requires Claude Code v2.1.89 or later. Earlier versions do not recognize it and the tool proceeds through the normal permission flow.

767 Use `hookSpecificOutput.permissionDecision` and

768 `hookSpecificOutput.permissionDecisionReason` instead. The deprecated fields

769 `"approve"` and `"block"` map to `"allow"` and `"deny"` respectively.

770</Note>1111</Note>

771 1112 

1113The `AskUserQuestion` tool is the typical case: Claude wants to ask the user something, but there is no terminal to answer in. The round trip works like this:

1114 

11151. Claude calls `AskUserQuestion`. The `PreToolUse` hook fires.

11162. The hook returns `permissionDecision: "defer"`. The tool does not execute. The process exits with `stop_reason: "tool_deferred"` and the pending tool call preserved in the transcript.

11173. The calling process reads `deferred_tool_use` from the SDK result, surfaces the question in its own UI, and waits for an answer.

11184. The calling process runs `claude -p --resume <session-id>`. The same tool call fires `PreToolUse` again.

11195. The hook returns `permissionDecision: "allow"` with the answer in `updatedInput`. The tool executes and Claude continues.

1120 

1121The `deferred_tool_use` field carries the tool's `id`, `name`, and `input`. The `input` is the parameters Claude generated for the tool call, captured before execution:

1122 

1123```json theme={null}

1124{

1125 "type": "result",

1126 "subtype": "success",

1127 "stop_reason": "tool_deferred",

1128 "session_id": "abc123",

1129 "deferred_tool_use": {

1130 "id": "toolu_01abc",

1131 "name": "AskUserQuestion",

1132 "input": { "questions": [{ "question": "Which framework?", "header": "Framework", "options": [{"label": "React"}, {"label": "Vue"}], "multiSelect": false }] }

1133 }

1134}

1135```

1136 

1137There is no timeout or retry limit. The session remains on disk until you resume it, subject to the [`cleanupPeriodDays`](/en/settings#available-settings) retention sweep that deletes session files after 30 days by default. If the answer is not ready when you resume, the hook can return `"defer"` again and the process exits the same way. The calling process controls when to break the loop by eventually returning `"allow"` or `"deny"` from the hook.

1138 

1139`"defer"` only works when Claude makes a single tool call in the turn. If Claude makes several tool calls at once, `"defer"` is ignored with a warning and the tool proceeds through the normal permission flow. The constraint exists because resume can only re-run one tool: there is no way to defer one call from a batch without leaving the others unresolved.

1140 

1141If the deferred tool is no longer available when you resume, the process exits with `stop_reason: "tool_deferred_unavailable"` and `is_error: true` before the hook fires. This happens when an MCP server that provided the tool is not connected for the resumed session. The `deferred_tool_use` payload is still included so you can identify which tool went missing.

1142 

1143<Warning>

1144 `--resume` does not restore the permission mode from the prior session. Pass the same `--permission-mode` flag on resume that was active when the tool was deferred. Claude Code logs a warning if the modes differ.

1145</Warning>

1146 

772### PermissionRequest1147### PermissionRequest

773 1148 

774Runs when the user is shown a permission dialog.1149Runs when the user is shown a permission dialog.


793 "description": "Remove node_modules directory"1168 "description": "Remove node_modules directory"

794 },1169 },

795 "permission_suggestions": [1170 "permission_suggestions": [

796 { "type": "toolAlwaysAllow", "tool": "Bash" }1171 {

1172 "type": "addRules",

1173 "rules": [{ "toolName": "Bash", "ruleContent": "rm -rf node_modules" }],

1174 "behavior": "allow",

1175 "destination": "localSettings"

1176 }

797 ]1177 ]

798}1178}

799```1179```


803`PermissionRequest` hooks can allow or deny permission requests. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return a `decision` object with these event-specific fields:1183`PermissionRequest` hooks can allow or deny permission requests. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return a `decision` object with these event-specific fields:

804 1184 

805| Field | Description |1185| Field | Description |

806| :------------------- | :------------------------------------------------------------------------------------------------------------- |1186| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

807| `behavior` | `"allow"` grants the permission, `"deny"` denies it |1187| `behavior` | `"allow"` grants the permission, `"deny"` denies it. [Deny and ask rules](/en/permissions#manage-permissions) are still evaluated, so a hook returning `"allow"` does not override a matching deny rule |

808| `updatedInput` | For `"allow"` only: modifies the tool's input parameters before execution |1188| `updatedInput` | For `"allow"` only: modifies the tool's input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. The modified input is re-evaluated against deny and ask rules |

809| `updatedPermissions` | For `"allow"` only: applies permission rule updates, equivalent to the user selecting an "always allow" option |1189| `updatedPermissions` | For `"allow"` only: array of [permission update entries](#permission-update-entries) to apply, such as adding an allow rule or changing the session permission mode |

810| `message` | For `"deny"` only: tells Claude why the permission was denied |1190| `message` | For `"deny"` only: tells Claude why the permission was denied |

811| `interrupt` | For `"deny"` only: if `true`, stops Claude |1191| `interrupt` | For `"deny"` only: if `true`, stops Claude |

812 1192 


824}1204}

825```1205```

826 1206 

1207#### Permission update entries

1208 

1209The `updatedPermissions` output field and the [`permission_suggestions` input field](#permissionrequest-input) both use the same array of entry objects. Each entry has a `type` that determines its other fields, and a `destination` that controls where the change is written.

1210 

1211| `type` | Fields | Effect |

1212| :------------------ | :--------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

1213| `addRules` | `rules`, `behavior`, `destination` | Adds permission rules. `rules` is an array of `{toolName, ruleContent?}` objects. Omit `ruleContent` to match the whole tool. `behavior` is `"allow"`, `"deny"`, or `"ask"` |

1214| `replaceRules` | `rules`, `behavior`, `destination` | Replaces all rules of the given `behavior` at the `destination` with the provided `rules` |

1215| `removeRules` | `rules`, `behavior`, `destination` | Removes matching rules of the given `behavior` |

1216| `setMode` | `mode`, `destination` | Changes the permission mode. Valid modes are `default`, `acceptEdits`, `dontAsk`, `bypassPermissions`, and `plan` |

1217| `addDirectories` | `directories`, `destination` | Adds working directories. `directories` is an array of path strings |

1218| `removeDirectories` | `directories`, `destination` | Removes working directories |

1219 

1220<Note>

1221 `setMode` with `bypassPermissions` only takes effect if the session was launched with bypass mode already available: `--dangerously-skip-permissions`, `--permission-mode bypassPermissions`, `--allow-dangerously-skip-permissions`, or `permissions.defaultMode: "bypassPermissions"` in settings, and the mode is not disabled by [`permissions.disableBypassPermissionsMode`](/en/permissions#managed-settings). Otherwise the update is a no-op. `bypassPermissions` is never persisted as `defaultMode` regardless of `destination`.

1222</Note>

1223 

1224The `destination` field on every entry determines whether the change stays in memory or persists to a settings file.

1225 

1226| `destination` | Writes to |

1227| :---------------- | :---------------------------------------------- |

1228| `session` | in-memory only, discarded when the session ends |

1229| `localSettings` | `.claude/settings.local.json` |

1230| `projectSettings` | `.claude/settings.json` |

1231| `userSettings` | `~/.claude/settings.json` |

1232 

1233A hook can echo one of the `permission_suggestions` it received as its own `updatedPermissions` output, which is equivalent to the user selecting that "always allow" option in the dialog.

1234 

827### PostToolUse1235### PostToolUse

828 1236 

829Runs immediately after a tool completes successfully.1237Runs immediately after a tool completes successfully.


850 "filePath": "/path/to/file.txt",1258 "filePath": "/path/to/file.txt",

851 "success": true1259 "success": true

852 },1260 },

853 "tool_use_id": "toolu_01ABC123..."1261 "tool_use_id": "toolu_01ABC123...",

1262 "duration_ms": 12

854}1263}

855```1264```

856 1265 

1266| Field | Description |

1267| :------------ | :------------------------------------------------------------------------------------------------------------ |

1268| `duration_ms` | Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks |

1269 

857#### PostToolUse decision control1270#### PostToolUse decision control

858 1271 

859`PostToolUse` hooks can provide feedback to Claude after tool execution. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return these event-specific fields:1272`PostToolUse` hooks can provide feedback to Claude after tool execution. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return these event-specific fields:


900 },1313 },

901 "tool_use_id": "toolu_01ABC123...",1314 "tool_use_id": "toolu_01ABC123...",

902 "error": "Command exited with non-zero status code 1",1315 "error": "Command exited with non-zero status code 1",

903 "is_interrupt": false1316 "is_interrupt": false,

1317 "duration_ms": 4187

904}1318}

905```1319```

906 1320 

907| Field | Description |1321| Field | Description |

908| :------------- | :------------------------------------------------------------------------------ |1322| :------------- | :------------------------------------------------------------------------------------------------------------ |

909| `error` | String describing what went wrong |1323| `error` | String describing what went wrong |

910| `is_interrupt` | Optional boolean indicating whether the failure was caused by user interruption |1324| `is_interrupt` | Optional boolean indicating whether the failure was caused by user interruption |

1325| `duration_ms` | Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks |

911 1326 

912#### PostToolUseFailure decision control1327#### PostToolUseFailure decision control

913 1328 


926}1341}

927```1342```

928 1343 

929### Notification1344### PostToolBatch

930 1345 

931Runs when Claude Code sends notifications. Matches on notification type: `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`. Omit the matcher to run hooks for all notification types.1346Runs once after every tool call in a batch has resolved, before Claude Code sends the next request to the model. `PostToolUse` fires once per tool, which means it fires concurrently when Claude makes parallel tool calls. `PostToolBatch` fires exactly once with the full batch, so it is the right place to inject context that depends on the set of tools that ran rather than on any single tool. There is no matcher for this event.

932 1347 

933Use separate matchers to run different handlers depending on the notification type. This configuration triggers a permission-specific alert script when Claude needs permission approval and a different notification when Claude has been idle:1348#### PostToolBatch input

1349 

1350In addition to the [common input fields](#common-input-fields), PostToolBatch hooks receive `tool_calls`, an array describing every tool call in the batch:

934 1351 

935```json theme={null}1352```json theme={null}

936{1353{

937 "hooks": {1354 "session_id": "abc123",

938 "Notification": [1355 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

939 {1356 "cwd": "/Users/...",

940 "matcher": "permission_prompt",1357 "permission_mode": "default",

941 "hooks": [1358 "hook_event_name": "PostToolBatch",

1359 "tool_calls": [

942 {1360 {

943 "type": "command",1361 "tool_name": "Read",

944 "command": "/path/to/permission-alert.sh"1362 "tool_input": {"file_path": "/.../ledger/accounts.py"},

945 }1363 "tool_use_id": "toolu_01...",

946 ]1364 "tool_response": " 1\tfrom __future__ import annotations\n 2\t..."

947 },1365 },

948 {1366 {

949 "matcher": "idle_prompt",1367 "tool_name": "Read",

950 "hooks": [1368 "tool_input": {"file_path": "/.../ledger/transactions.py"},

951 {1369 "tool_use_id": "toolu_02...",

952 "type": "command",1370 "tool_response": " 1\tfrom __future__ import annotations\n 2\t..."

953 "command": "/path/to/idle-notification.sh"

954 }1371 }

955 ]1372 ]

956 }

957 ]

958 }

959}1373}

960```1374```

961 1375 

962#### Notification input1376`tool_response` contains the same content the model receives in the corresponding `tool_result` block. The value is a serialized string or content-block array, exactly as the tool emitted it. For `Read`, that means line-number-prefixed text rather than raw file contents. Responses can be large, so parse only the fields you need.

963 1377 

964In addition to the [common input fields](#common-input-fields), Notification hooks receive `message` with the notification text, an optional `title`, and `notification_type` indicating which type fired.1378<Note>

1379 The `tool_response` shape differs from `PostToolUse`'s. `PostToolUse` passes the tool's structured `Output` object, such as `{filePath: "...", success: true}` for `Write`; `PostToolBatch` passes the serialized `tool_result` content the model sees.

1380</Note>

1381 

1382#### PostToolBatch decision control

1383 

1384`PostToolBatch` hooks can inject context for Claude. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return these event-specific fields:

1385 

1386| Field | Description |

1387| :------------------ | :------------------------------------------------------ |

1388| `additionalContext` | Context string injected once before the next model call |

965 1389 

966```json theme={null}1390```json theme={null}

967{1391{

968 "session_id": "abc123",1392 "hookSpecificOutput": {

969 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",1393 "hookEventName": "PostToolBatch",

970 "cwd": "/Users/...",1394 "additionalContext": "These files are part of the ledger module. Run pytest before marking the task complete."

971 "permission_mode": "default",1395 }

972 "hook_event_name": "Notification",

973 "message": "Claude needs your permission to use Bash",

974 "title": "Permission needed",

975 "notification_type": "permission_prompt"

976}1396}

977```1397```

978 1398 

979Notification hooks cannot block or modify notifications. In addition to the [JSON output fields](#json-output) available to all hooks, you can return `additionalContext` to add context to the conversation:1399<Note>

1400 Injected `additionalContext` is persisted to the session transcript. On `--continue` or `--resume`, the saved text is replayed from disk and the hook does not re-run for past turns. Prefer static context such as conventions or file-type guidance over dynamic values like timestamps or the current commit SHA, since those become stale on resume.

980 1401 

981| Field | Description |1402 Frame the context as factual information rather than imperative system instructions. Text written as out-of-band system commands can trigger Claude's prompt-injection defenses, which surfaces the injection to the user instead of acting on it.

982| :------------------ | :------------------------------- |1403</Note>

983| `additionalContext` | String added to Claude's context |

984 1404 

985### SubagentStart1405Returning `decision: "block"` or `continue: false` stops the agentic loop before the next model call.

986 1406 

987Runs when a Claude Code subagent is spawned via the Task tool. Supports matchers to filter by agent type name (built-in agents like `Bash`, `Explore`, `Plan`, or custom agent names from `.claude/agents/`).1407### PermissionDenied

988 1408 

989#### SubagentStart input1409Runs when the [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) classifier denies a tool call. This hook only fires in auto mode: it does not run when you manually deny a permission dialog, when a `PreToolUse` hook blocks a call, or when a `deny` rule matches. Use it to log classifier denials, adjust configuration, or tell the model it may retry the tool call.

990 1410 

991In addition to the [common input fields](#common-input-fields), SubagentStart hooks receive `agent_id` with the unique identifier for the subagent and `agent_type` with the agent name (built-in agents like `"Bash"`, `"Explore"`, `"Plan"`, or custom agent names).1411Matches on tool name, same values as PreToolUse.

992 1412 

993```json theme={null}1413#### PermissionDenied input

1414 

1415In addition to the [common input fields](#common-input-fields), PermissionDenied hooks receive `tool_name`, `tool_input`, `tool_use_id`, and `reason`.

1416 

1417```json theme={null}

1418{

1419 "session_id": "abc123",

1420 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1421 "cwd": "/Users/...",

1422 "permission_mode": "auto",

1423 "hook_event_name": "PermissionDenied",

1424 "tool_name": "Bash",

1425 "tool_input": {

1426 "command": "rm -rf /tmp/build",

1427 "description": "Clean build directory"

1428 },

1429 "tool_use_id": "toolu_01ABC123...",

1430 "reason": "Auto mode denied: command targets a path outside the project"

1431}

1432```

1433 

1434| Field | Description |

1435| :------- | :------------------------------------------------------------ |

1436| `reason` | The classifier's explanation for why the tool call was denied |

1437 

1438#### PermissionDenied decision control

1439 

1440PermissionDenied hooks can tell the model it may retry the denied tool call. Return a JSON object with `hookSpecificOutput.retry` set to `true`:

1441 

1442```json theme={null}

1443{

1444 "hookSpecificOutput": {

1445 "hookEventName": "PermissionDenied",

1446 "retry": true

1447 }

1448}

1449```

1450 

1451When `retry` is `true`, Claude Code adds a message to the conversation telling the model it may retry the tool call. The denial itself is not reversed. If your hook does not return JSON, or returns `retry: false`, the denial stands and the model receives the original rejection message.

1452 

1453### Notification

1454 

1455Runs when Claude Code sends notifications. Matches on notification type: `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`. Omit the matcher to run hooks for all notification types.

1456 

1457Use separate matchers to run different handlers depending on the notification type. This configuration triggers a permission-specific alert script when Claude needs permission approval and a different notification when Claude has been idle:

1458 

1459```json theme={null}

1460{

1461 "hooks": {

1462 "Notification": [

1463 {

1464 "matcher": "permission_prompt",

1465 "hooks": [

1466 {

1467 "type": "command",

1468 "command": "/path/to/permission-alert.sh"

1469 }

1470 ]

1471 },

1472 {

1473 "matcher": "idle_prompt",

1474 "hooks": [

1475 {

1476 "type": "command",

1477 "command": "/path/to/idle-notification.sh"

1478 }

1479 ]

1480 }

1481 ]

1482 }

1483}

1484```

1485 

1486#### Notification input

1487 

1488In addition to the [common input fields](#common-input-fields), Notification hooks receive `message` with the notification text, an optional `title`, and `notification_type` indicating which type fired.

1489 

1490```json theme={null}

1491{

1492 "session_id": "abc123",

1493 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1494 "cwd": "/Users/...",

1495 "hook_event_name": "Notification",

1496 "message": "Claude needs your permission to use Bash",

1497 "title": "Permission needed",

1498 "notification_type": "permission_prompt"

1499}

1500```

1501 

1502Notification hooks cannot block or modify notifications. In addition to the [JSON output fields](#json-output) available to all hooks, you can return `additionalContext` to add context to the conversation:

1503 

1504| Field | Description |

1505| :------------------ | :------------------------------- |

1506| `additionalContext` | String added to Claude's context |

1507 

1508### SubagentStart

1509 

1510Runs when a Claude Code subagent is spawned via the Agent tool. Supports matchers to filter by agent type name (built-in agents like `Bash`, `Explore`, `Plan`, or custom agent names from `.claude/agents/`).

1511 

1512#### SubagentStart input

1513 

1514In addition to the [common input fields](#common-input-fields), SubagentStart hooks receive `agent_id` with the unique identifier for the subagent and `agent_type` with the agent name (built-in agents like `"Bash"`, `"Explore"`, `"Plan"`, or custom agent names).

1515 

1516```json theme={null}

994{1517{

995 "session_id": "abc123",1518 "session_id": "abc123",

996 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",1519 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

997 "cwd": "/Users/...",1520 "cwd": "/Users/...",

998 "permission_mode": "default",

999 "hook_event_name": "SubagentStart",1521 "hook_event_name": "SubagentStart",

1000 "agent_id": "agent-abc123",1522 "agent_id": "agent-abc123",

1001 "agent_type": "Explore"1523 "agent_type": "Explore"


1023 1545 

1024#### SubagentStop input1546#### SubagentStop input

1025 1547 

1026In addition to the [common input fields](#common-input-fields), SubagentStop hooks receive `stop_hook_active`, `agent_id`, `agent_type`, and `agent_transcript_path`. The `agent_type` field is the value used for matcher filtering. The `transcript_path` is the main session's transcript, while `agent_transcript_path` is the subagent's own transcript stored in a nested `subagents/` folder.1548In addition to the [common input fields](#common-input-fields), SubagentStop hooks receive `stop_hook_active`, `agent_id`, `agent_type`, `agent_transcript_path`, and `last_assistant_message`. The `agent_type` field is the value used for matcher filtering. The `transcript_path` is the main session's transcript, while `agent_transcript_path` is the subagent's own transcript stored in a nested `subagents/` folder. The `last_assistant_message` field contains the text content of the subagent's final response, so hooks can access it without parsing the transcript file.

1027 1549 

1028```json theme={null}1550```json theme={null}

1029{1551{


1035 "stop_hook_active": false,1557 "stop_hook_active": false,

1036 "agent_id": "def456",1558 "agent_id": "def456",

1037 "agent_type": "Explore",1559 "agent_type": "Explore",

1038 "agent_transcript_path": "~/.claude/projects/.../abc123/subagents/agent-def456.jsonl"1560 "agent_transcript_path": "~/.claude/projects/.../abc123/subagents/agent-def456.jsonl",

1561 "last_assistant_message": "Analysis complete. Found 3 potential issues..."

1039}1562}

1040```1563```

1041 1564 

1042SubagentStop hooks use the same decision control format as [Stop hooks](#stop-decision-control).1565SubagentStop hooks use the same decision control format as [Stop hooks](#stop-decision-control).

1043 1566 

1567### TaskCreated

1568 

1569Runs when a task is being created via the `TaskCreate` tool. Use this to enforce naming conventions, require task descriptions, or prevent certain tasks from being created.

1570 

1571When a `TaskCreated` hook exits with code 2, the task is not created and the stderr message is fed back to the model as feedback. To stop the teammate entirely instead of re-running it, return JSON with `{"continue": false, "stopReason": "..."}`. TaskCreated hooks do not support matchers and fire on every occurrence.

1572 

1573#### TaskCreated input

1574 

1575In addition to the [common input fields](#common-input-fields), TaskCreated hooks receive `task_id`, `task_subject`, and optionally `task_description`, `teammate_name`, and `team_name`.

1576 

1577```json theme={null}

1578{

1579 "session_id": "abc123",

1580 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1581 "cwd": "/Users/...",

1582 "permission_mode": "default",

1583 "hook_event_name": "TaskCreated",

1584 "task_id": "task-001",

1585 "task_subject": "Implement user authentication",

1586 "task_description": "Add login and signup endpoints",

1587 "teammate_name": "implementer",

1588 "team_name": "my-project"

1589}

1590```

1591 

1592| Field | Description |

1593| :----------------- | :---------------------------------------------------- |

1594| `task_id` | Identifier of the task being created |

1595| `task_subject` | Title of the task |

1596| `task_description` | Detailed description of the task. May be absent |

1597| `teammate_name` | Name of the teammate creating the task. May be absent |

1598| `team_name` | Name of the team. May be absent |

1599 

1600#### TaskCreated decision control

1601 

1602TaskCreated hooks support two ways to control task creation:

1603 

1604* **Exit code 2**: the task is not created and the stderr message is fed back to the model as feedback.

1605* **JSON `{"continue": false, "stopReason": "..."}`**: stops the teammate entirely, matching `Stop` hook behavior. The `stopReason` is shown to the user.

1606 

1607This example blocks tasks whose subjects don't follow the required format:

1608 

1609```bash theme={null}

1610#!/bin/bash

1611INPUT=$(cat)

1612TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')

1613 

1614if [[ ! "$TASK_SUBJECT" =~ ^\[TICKET-[0-9]+\] ]]; then

1615 echo "Task subject must start with a ticket number, e.g. '[TICKET-123] Add feature'" >&2

1616 exit 2

1617fi

1618 

1619exit 0

1620```

1621 

1622### TaskCompleted

1623 

1624Runs when a task is being marked as completed. This fires in two situations: when any agent explicitly marks a task as completed through the TaskUpdate tool, or when an [agent team](/en/agent-teams) teammate finishes its turn with in-progress tasks. Use this to enforce completion criteria like passing tests or lint checks before a task can close.

1625 

1626When a `TaskCompleted` hook exits with code 2, the task is not marked as completed and the stderr message is fed back to the model as feedback. To stop the teammate entirely instead of re-running it, return JSON with `{"continue": false, "stopReason": "..."}`. TaskCompleted hooks do not support matchers and fire on every occurrence.

1627 

1628#### TaskCompleted input

1629 

1630In addition to the [common input fields](#common-input-fields), TaskCompleted hooks receive `task_id`, `task_subject`, and optionally `task_description`, `teammate_name`, and `team_name`.

1631 

1632```json theme={null}

1633{

1634 "session_id": "abc123",

1635 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1636 "cwd": "/Users/...",

1637 "permission_mode": "default",

1638 "hook_event_name": "TaskCompleted",

1639 "task_id": "task-001",

1640 "task_subject": "Implement user authentication",

1641 "task_description": "Add login and signup endpoints",

1642 "teammate_name": "implementer",

1643 "team_name": "my-project"

1644}

1645```

1646 

1647| Field | Description |

1648| :----------------- | :------------------------------------------------------ |

1649| `task_id` | Identifier of the task being completed |

1650| `task_subject` | Title of the task |

1651| `task_description` | Detailed description of the task. May be absent |

1652| `teammate_name` | Name of the teammate completing the task. May be absent |

1653| `team_name` | Name of the team. May be absent |

1654 

1655#### TaskCompleted decision control

1656 

1657TaskCompleted hooks support two ways to control task completion:

1658 

1659* **Exit code 2**: the task is not marked as completed and the stderr message is fed back to the model as feedback.

1660* **JSON `{"continue": false, "stopReason": "..."}`**: stops the teammate entirely, matching `Stop` hook behavior. The `stopReason` is shown to the user.

1661 

1662This example runs tests and blocks task completion if they fail:

1663 

1664```bash theme={null}

1665#!/bin/bash

1666INPUT=$(cat)

1667TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')

1668 

1669# Run the test suite

1670if ! npm test 2>&1; then

1671 echo "Tests not passing. Fix failing tests before completing: $TASK_SUBJECT" >&2

1672 exit 2

1673fi

1674 

1675exit 0

1676```

1677 

1044### Stop1678### Stop

1045 1679 

1046Runs when the main Claude Code agent has finished responding. Does not run if1680Runs when the main Claude Code agent has finished responding. Does not run if

1047the stoppage occurred due to a user interrupt.1681the stoppage occurred due to a user interrupt. API errors fire

1682[StopFailure](#stopfailure) instead.

1048 1683 

1049#### Stop input1684#### Stop input

1050 1685 

1051In addition to the [common input fields](#common-input-fields), Stop hooks receive `stop_hook_active`. This field is `true` when Claude Code is already continuing as a result of a stop hook. Check this value or process the transcript to prevent Claude Code from running indefinitely.1686In addition to the [common input fields](#common-input-fields), Stop hooks receive `stop_hook_active` and `last_assistant_message`. The `stop_hook_active` field is `true` when Claude Code is already continuing as a result of a stop hook. Check this value or process the transcript to prevent Claude Code from running indefinitely. The `last_assistant_message` field contains the text content of Claude's final response, so hooks can access it without parsing the transcript file.

1052 1687 

1053```json theme={null}1688```json theme={null}

1054{1689{


1057 "cwd": "/Users/...",1692 "cwd": "/Users/...",

1058 "permission_mode": "default",1693 "permission_mode": "default",

1059 "hook_event_name": "Stop",1694 "hook_event_name": "Stop",

1060 "stop_hook_active": true1695 "stop_hook_active": true,

1696 "last_assistant_message": "I've completed the refactoring. Here's a summary..."

1061}1697}

1062```1698```

1063 1699 


1077}1713}

1078```1714```

1079 1715 

1716### StopFailure

1717 

1718Runs instead of [Stop](#stop) when the turn ends due to an API error. Output and exit code are ignored. Use this to log failures, send alerts, or take recovery actions when Claude cannot complete a response due to rate limits, authentication problems, or other API errors.

1719 

1720#### StopFailure input

1721 

1722In addition to the [common input fields](#common-input-fields), StopFailure hooks receive `error`, optional `error_details`, and optional `last_assistant_message`. The `error` field identifies the error type and is used for matcher filtering.

1723 

1724| Field | Description |

1725| :----------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

1726| `error` | Error type: `rate_limit`, `authentication_failed`, `billing_error`, `invalid_request`, `server_error`, `max_output_tokens`, or `unknown` |

1727| `error_details` | Additional details about the error, when available |

1728| `last_assistant_message` | The rendered error text shown in the conversation. Unlike `Stop` and `SubagentStop`, where this field holds Claude's conversational output, for `StopFailure` it contains the API error string itself, such as `"API Error: Rate limit reached"` |

1729 

1730```json theme={null}

1731{

1732 "session_id": "abc123",

1733 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1734 "cwd": "/Users/...",

1735 "hook_event_name": "StopFailure",

1736 "error": "rate_limit",

1737 "error_details": "429 Too Many Requests",

1738 "last_assistant_message": "API Error: Rate limit reached"

1739}

1740```

1741 

1742StopFailure hooks have no decision control. They run for notification and logging purposes only.

1743 

1744### TeammateIdle

1745 

1746Runs when an [agent team](/en/agent-teams) teammate is about to go idle after finishing its turn. Use this to enforce quality gates before a teammate stops working, such as requiring passing lint checks or verifying that output files exist.

1747 

1748When a `TeammateIdle` hook exits with code 2, the teammate receives the stderr message as feedback and continues working instead of going idle. To stop the teammate entirely instead of re-running it, return JSON with `{"continue": false, "stopReason": "..."}`. TeammateIdle hooks do not support matchers and fire on every occurrence.

1749 

1750#### TeammateIdle input

1751 

1752In addition to the [common input fields](#common-input-fields), TeammateIdle hooks receive `teammate_name` and `team_name`.

1753 

1754```json theme={null}

1755{

1756 "session_id": "abc123",

1757 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1758 "cwd": "/Users/...",

1759 "permission_mode": "default",

1760 "hook_event_name": "TeammateIdle",

1761 "teammate_name": "researcher",

1762 "team_name": "my-project"

1763}

1764```

1765 

1766| Field | Description |

1767| :-------------- | :-------------------------------------------- |

1768| `teammate_name` | Name of the teammate that is about to go idle |

1769| `team_name` | Name of the team |

1770 

1771#### TeammateIdle decision control

1772 

1773TeammateIdle hooks support two ways to control teammate behavior:

1774 

1775* **Exit code 2**: the teammate receives the stderr message as feedback and continues working instead of going idle.

1776* **JSON `{"continue": false, "stopReason": "..."}`**: stops the teammate entirely, matching `Stop` hook behavior. The `stopReason` is shown to the user.

1777 

1778This example checks that a build artifact exists before allowing a teammate to go idle:

1779 

1780```bash theme={null}

1781#!/bin/bash

1782 

1783if [ ! -f "./dist/output.js" ]; then

1784 echo "Build artifact missing. Run the build before stopping." >&2

1785 exit 2

1786fi

1787 

1788exit 0

1789```

1790 

1791### ConfigChange

1792 

1793Runs when a configuration file changes during a session. Use this to audit settings changes, enforce security policies, or block unauthorized modifications to configuration files.

1794 

1795ConfigChange hooks fire for changes to settings files, managed policy settings, and skill files. The `source` field in the input tells you which type of configuration changed, and the optional `file_path` field provides the path to the changed file.

1796 

1797The matcher filters on the configuration source:

1798 

1799| Matcher | When it fires |

1800| :----------------- | :---------------------------------------- |

1801| `user_settings` | `~/.claude/settings.json` changes |

1802| `project_settings` | `.claude/settings.json` changes |

1803| `local_settings` | `.claude/settings.local.json` changes |

1804| `policy_settings` | Managed policy settings change |

1805| `skills` | A skill file in `.claude/skills/` changes |

1806 

1807This example logs all configuration changes for security auditing:

1808 

1809```json theme={null}

1810{

1811 "hooks": {

1812 "ConfigChange": [

1813 {

1814 "hooks": [

1815 {

1816 "type": "command",

1817 "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit-config-change.sh"

1818 }

1819 ]

1820 }

1821 ]

1822 }

1823}

1824```

1825 

1826#### ConfigChange input

1827 

1828In addition to the [common input fields](#common-input-fields), ConfigChange hooks receive `source` and optionally `file_path`. The `source` field indicates which configuration type changed, and `file_path` provides the path to the specific file that was modified.

1829 

1830```json theme={null}

1831{

1832 "session_id": "abc123",

1833 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1834 "cwd": "/Users/...",

1835 "hook_event_name": "ConfigChange",

1836 "source": "project_settings",

1837 "file_path": "/Users/.../my-project/.claude/settings.json"

1838}

1839```

1840 

1841#### ConfigChange decision control

1842 

1843ConfigChange hooks can block configuration changes from taking effect. Use exit code 2 or a JSON `decision` to prevent the change. When blocked, the new settings are not applied to the running session.

1844 

1845| Field | Description |

1846| :--------- | :--------------------------------------------------------------------------------------- |

1847| `decision` | `"block"` prevents the configuration change from being applied. Omit to allow the change |

1848| `reason` | Explanation shown to the user when `decision` is `"block"` |

1849 

1850```json theme={null}

1851{

1852 "decision": "block",

1853 "reason": "Configuration changes to project settings require admin approval"

1854}

1855```

1856 

1857`policy_settings` changes cannot be blocked. Hooks still fire for `policy_settings` sources, so you can use them for audit logging, but any blocking decision is ignored. This ensures enterprise-managed settings always take effect.

1858 

1859### CwdChanged

1860 

1861Runs when the working directory changes during a session, for example when Claude executes a `cd` command. Use this to react to directory changes: reload environment variables, activate project-specific toolchains, or run setup scripts automatically. Pairs with [FileChanged](#filechanged) for tools like [direnv](https://direnv.net/) that manage per-directory environment.

1862 

1863CwdChanged hooks have access to `CLAUDE_ENV_FILE`. Variables written to that file persist into subsequent Bash commands for the session, just as in [SessionStart hooks](#persist-environment-variables).

1864 

1865CwdChanged does not support matchers and fires on every directory change.

1866 

1867#### CwdChanged input

1868 

1869In addition to the [common input fields](#common-input-fields), CwdChanged hooks receive `old_cwd` and `new_cwd`.

1870 

1871```json theme={null}

1872{

1873 "session_id": "abc123",

1874 "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",

1875 "cwd": "/Users/my-project/src",

1876 "hook_event_name": "CwdChanged",

1877 "old_cwd": "/Users/my-project",

1878 "new_cwd": "/Users/my-project/src"

1879}

1880```

1881 

1882#### CwdChanged output

1883 

1884In addition to the [JSON output fields](#json-output) available to all hooks, CwdChanged hooks can return `watchPaths` to dynamically set which file paths [FileChanged](#filechanged) watches:

1885 

1886| Field | Description |

1887| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

1888| `watchPaths` | Array of absolute paths. Replaces the current dynamic watch list (paths from your `matcher` configuration are always watched). Returning an empty array clears the dynamic list, which is typical when entering a new directory |

1889 

1890CwdChanged hooks have no decision control. They cannot block the directory change.

1891 

1892### FileChanged

1893 

1894Runs when a watched file changes on disk. Useful for reloading environment variables when project configuration files are modified.

1895 

1896The `matcher` for this event serves two roles:

1897 

1898* **Build the watch list**: the value is split on `|` and each segment is registered as a literal filename in the working directory, so `".envrc|.env"` watches exactly those two files. Regex patterns are not useful here: a value like `^\.env` would watch a file literally named `^\.env`.

1899* **Filter which hooks run**: when a watched file changes, the same value filters which hook groups run using the standard [matcher rules](#matcher-patterns) against the changed file's basename.

1900 

1901FileChanged hooks have access to `CLAUDE_ENV_FILE`. Variables written to that file persist into subsequent Bash commands for the session, just as in [SessionStart hooks](#persist-environment-variables).

1902 

1903#### FileChanged input

1904 

1905In addition to the [common input fields](#common-input-fields), FileChanged hooks receive `file_path` and `event`.

1906 

1907| Field | Description |

1908| :---------- | :---------------------------------------------------------------------------------------------- |

1909| `file_path` | Absolute path to the file that changed |

1910| `event` | What happened: `"change"` (file modified), `"add"` (file created), or `"unlink"` (file deleted) |

1911 

1912```json theme={null}

1913{

1914 "session_id": "abc123",

1915 "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",

1916 "cwd": "/Users/my-project",

1917 "hook_event_name": "FileChanged",

1918 "file_path": "/Users/my-project/.envrc",

1919 "event": "change"

1920}

1921```

1922 

1923#### FileChanged output

1924 

1925In addition to the [JSON output fields](#json-output) available to all hooks, FileChanged hooks can return `watchPaths` to dynamically update which file paths are watched:

1926 

1927| Field | Description |

1928| :----------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

1929| `watchPaths` | Array of absolute paths. Replaces the current dynamic watch list (paths from your `matcher` configuration are always watched). Use this when your hook script discovers additional files to watch based on the changed file |

1930 

1931FileChanged hooks have no decision control. They cannot block the file change from occurring.

1932 

1933### WorktreeCreate

1934 

1935When you run `claude --worktree` or a [subagent uses `isolation: "worktree"`](/en/sub-agents#choose-the-subagent-scope), Claude Code creates an isolated working copy using `git worktree`. If you configure a WorktreeCreate hook, it replaces the default git behavior, letting you use a different version control system like SVN, Perforce, or Mercurial.

1936 

1937Because the hook replaces the default behavior entirely, [`.worktreeinclude`](/en/common-workflows#copy-gitignored-files-to-worktrees) is not processed. If you need to copy local configuration files like `.env` into the new worktree, do it inside your hook script.

1938 

1939The hook must return the absolute path to the created worktree directory. Claude Code uses this path as the working directory for the isolated session. Command hooks print it on stdout; HTTP hooks return it via `hookSpecificOutput.worktreePath`.

1940 

1941This example creates an SVN working copy and prints the path for Claude Code to use. Replace the repository URL with your own:

1942 

1943```json theme={null}

1944{

1945 "hooks": {

1946 "WorktreeCreate": [

1947 {

1948 "hooks": [

1949 {

1950 "type": "command",

1951 "command": "bash -c 'NAME=$(jq -r .name); DIR=\"$HOME/.claude/worktrees/$NAME\"; svn checkout https://svn.example.com/repo/trunk \"$DIR\" >&2 && echo \"$DIR\"'"

1952 }

1953 ]

1954 }

1955 ]

1956 }

1957}

1958```

1959 

1960The hook reads the worktree `name` from the JSON input on stdin, checks out a fresh copy into a new directory, and prints the directory path. The `echo` on the last line is what Claude Code reads as the worktree path. Redirect any other output to stderr so it doesn't interfere with the path.

1961 

1962#### WorktreeCreate input

1963 

1964In addition to the [common input fields](#common-input-fields), WorktreeCreate hooks receive the `name` field. This is a slug identifier for the new worktree, either specified by the user or auto-generated (for example, `bold-oak-a3f2`).

1965 

1966```json theme={null}

1967{

1968 "session_id": "abc123",

1969 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1970 "cwd": "/Users/...",

1971 "hook_event_name": "WorktreeCreate",

1972 "name": "feature-auth"

1973}

1974```

1975 

1976#### WorktreeCreate output

1977 

1978WorktreeCreate hooks do not use the standard allow/block decision model. Instead, the hook's success or failure determines the outcome. The hook must return the absolute path to the created worktree directory:

1979 

1980* **Command hooks** (`type: "command"`): print the path on stdout.

1981* **HTTP hooks** (`type: "http"`): return `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }` in the response body.

1982 

1983If the hook fails or produces no path, worktree creation fails with an error.

1984 

1985### WorktreeRemove

1986 

1987The cleanup counterpart to [WorktreeCreate](#worktreecreate). This hook fires when a worktree is being removed, either when you exit a `--worktree` session and choose to remove it, or when a subagent with `isolation: "worktree"` finishes. For git-based worktrees, Claude handles cleanup automatically with `git worktree remove`. If you configured a WorktreeCreate hook for a non-git version control system, pair it with a WorktreeRemove hook to handle cleanup. Without one, the worktree directory is left on disk.

1988 

1989Claude Code passes the path returned by WorktreeCreate as `worktree_path` in the hook input. This example reads that path and removes the directory:

1990 

1991```json theme={null}

1992{

1993 "hooks": {

1994 "WorktreeRemove": [

1995 {

1996 "hooks": [

1997 {

1998 "type": "command",

1999 "command": "bash -c 'jq -r .worktree_path | xargs rm -rf'"

2000 }

2001 ]

2002 }

2003 ]

2004 }

2005}

2006```

2007 

2008#### WorktreeRemove input

2009 

2010In addition to the [common input fields](#common-input-fields), WorktreeRemove hooks receive the `worktree_path` field, which is the absolute path to the worktree being removed.

2011 

2012```json theme={null}

2013{

2014 "session_id": "abc123",

2015 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2016 "cwd": "/Users/...",

2017 "hook_event_name": "WorktreeRemove",

2018 "worktree_path": "/Users/.../my-project/.claude/worktrees/feature-auth"

2019}

2020```

2021 

2022WorktreeRemove hooks have no decision control. They cannot block worktree removal but can perform cleanup tasks like removing version control state or archiving changes. Hook failures are logged in debug mode only.

2023 

1080### PreCompact2024### PreCompact

1081 2025 

1082Runs before Claude Code is about to run a compact operation.2026Runs before Claude Code is about to run a compact operation.


1088| `manual` | `/compact` |2032| `manual` | `/compact` |

1089| `auto` | Auto-compact when the context window is full |2033| `auto` | Auto-compact when the context window is full |

1090 2034 

2035Exit with code 2 to block compaction. For a manual `/compact`, the stderr message is shown to the user. You can also block by returning JSON with `"decision": "block"`.

2036 

2037Blocking automatic compaction has different effects depending on when it fires. If compaction was triggered proactively before the context limit, Claude Code skips it and the conversation continues uncompacted. If compaction was triggered to recover from a context-limit error already returned by the API, the underlying error surfaces and the current request fails.

2038 

1091#### PreCompact input2039#### PreCompact input

1092 2040 

1093In addition to the [common input fields](#common-input-fields), PreCompact hooks receive `trigger` and `custom_instructions`. For `manual`, `custom_instructions` contains what the user passes into `/compact`. For `auto`, `custom_instructions` is empty.2041In addition to the [common input fields](#common-input-fields), PreCompact hooks receive `trigger` and `custom_instructions`. For `manual`, `custom_instructions` contains what the user passes into `/compact`. For `auto`, `custom_instructions` is empty.


1097 "session_id": "abc123",2045 "session_id": "abc123",

1098 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",2046 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1099 "cwd": "/Users/...",2047 "cwd": "/Users/...",

1100 "permission_mode": "default",

1101 "hook_event_name": "PreCompact",2048 "hook_event_name": "PreCompact",

1102 "trigger": "manual",2049 "trigger": "manual",

1103 "custom_instructions": ""2050 "custom_instructions": ""

1104}2051}

1105```2052```

1106 2053 

2054### PostCompact

2055 

2056Runs after Claude Code completes a compact operation. Use this event to react to the new compacted state, for example to log the generated summary or update external state.

2057 

2058The same matcher values apply as for `PreCompact`:

2059 

2060| Matcher | When it fires |

2061| :------- | :------------------------------------------------- |

2062| `manual` | After `/compact` |

2063| `auto` | After auto-compact when the context window is full |

2064 

2065#### PostCompact input

2066 

2067In addition to the [common input fields](#common-input-fields), PostCompact hooks receive `trigger` and `compact_summary`. The `compact_summary` field contains the conversation summary generated by the compact operation.

2068 

2069```json theme={null}

2070{

2071 "session_id": "abc123",

2072 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2073 "cwd": "/Users/...",

2074 "hook_event_name": "PostCompact",

2075 "trigger": "manual",

2076 "compact_summary": "Summary of the compacted conversation..."

2077}

2078```

2079 

2080PostCompact hooks have no decision control. They cannot affect the compaction result but can perform follow-up tasks.

2081 

1107### SessionEnd2082### SessionEnd

1108 2083 

1109Runs when a Claude Code session ends. Useful for cleanup tasks, logging session2084Runs when a Claude Code session ends. Useful for cleanup tasks, logging session


1114| Reason | Description |2089| Reason | Description |

1115| :---------------------------- | :----------------------------------------- |2090| :---------------------------- | :----------------------------------------- |

1116| `clear` | Session cleared with `/clear` command |2091| `clear` | Session cleared with `/clear` command |

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

1117| `logout` | User logged out |2093| `logout` | User logged out |

1118| `prompt_input_exit` | User exited while prompt input was visible |2094| `prompt_input_exit` | User exited while prompt input was visible |

1119| `bypass_permissions_disabled` | Bypass permissions mode was disabled |2095| `bypass_permissions_disabled` | Bypass permissions mode was disabled |


1128 "session_id": "abc123",2104 "session_id": "abc123",

1129 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",2105 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

1130 "cwd": "/Users/...",2106 "cwd": "/Users/...",

1131 "permission_mode": "default",

1132 "hook_event_name": "SessionEnd",2107 "hook_event_name": "SessionEnd",

1133 "reason": "other"2108 "reason": "other"

1134}2109}


1136 2111 

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

1138 2113 

2114SessionEnd hooks have a default timeout of 1.5 seconds. This applies to session exit, `/clear`, and switching sessions via interactive `/resume`. If a hook needs more time, set a per-hook `timeout` in the hook configuration. The overall budget is automatically raised to the highest per-hook timeout configured in settings files, up to 60 seconds. Timeouts set on plugin-provided hooks do not raise the budget. To override the budget explicitly, set the `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` environment variable in milliseconds.

2115 

2116```bash theme={null}

2117CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude

2118```

2119 

2120### Elicitation

2121 

2122Runs when an MCP server requests user input mid-task. By default, Claude Code shows an interactive dialog for the user to respond. Hooks can intercept this request and respond programmatically, skipping the dialog entirely.

2123 

2124The matcher field matches against the MCP server name.

2125 

2126#### Elicitation input

2127 

2128In addition to the [common input fields](#common-input-fields), Elicitation hooks receive `mcp_server_name`, `message`, and optional `mode`, `url`, `elicitation_id`, and `requested_schema` fields.

2129 

2130For form-mode elicitation (the most common case):

2131 

2132```json theme={null}

2133{

2134 "session_id": "abc123",

2135 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2136 "cwd": "/Users/...",

2137 "permission_mode": "default",

2138 "hook_event_name": "Elicitation",

2139 "mcp_server_name": "my-mcp-server",

2140 "message": "Please provide your credentials",

2141 "mode": "form",

2142 "requested_schema": {

2143 "type": "object",

2144 "properties": {

2145 "username": { "type": "string", "title": "Username" }

2146 }

2147 }

2148}

2149```

2150 

2151For URL-mode elicitation (browser-based authentication):

2152 

2153```json theme={null}

2154{

2155 "session_id": "abc123",

2156 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2157 "cwd": "/Users/...",

2158 "permission_mode": "default",

2159 "hook_event_name": "Elicitation",

2160 "mcp_server_name": "my-mcp-server",

2161 "message": "Please authenticate",

2162 "mode": "url",

2163 "url": "https://auth.example.com/login"

2164}

2165```

2166 

2167#### Elicitation output

2168 

2169To respond programmatically without showing the dialog, return a JSON object with `hookSpecificOutput`:

2170 

2171```json theme={null}

2172{

2173 "hookSpecificOutput": {

2174 "hookEventName": "Elicitation",

2175 "action": "accept",

2176 "content": {

2177 "username": "alice"

2178 }

2179 }

2180}

2181```

2182 

2183| Field | Values | Description |

2184| :-------- | :---------------------------- | :--------------------------------------------------------------- |

2185| `action` | `accept`, `decline`, `cancel` | Whether to accept, decline, or cancel the request |

2186| `content` | object | Form field values to submit. Only used when `action` is `accept` |

2187 

2188Exit code 2 denies the elicitation and shows stderr to the user.

2189 

2190### ElicitationResult

2191 

2192Runs after a user responds to an MCP elicitation. Hooks can observe, modify, or block the response before it is sent back to the MCP server.

2193 

2194The matcher field matches against the MCP server name.

2195 

2196#### ElicitationResult input

2197 

2198In addition to the [common input fields](#common-input-fields), ElicitationResult hooks receive `mcp_server_name`, `action`, and optional `mode`, `elicitation_id`, and `content` fields.

2199 

2200```json theme={null}

2201{

2202 "session_id": "abc123",

2203 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2204 "cwd": "/Users/...",

2205 "permission_mode": "default",

2206 "hook_event_name": "ElicitationResult",

2207 "mcp_server_name": "my-mcp-server",

2208 "action": "accept",

2209 "content": { "username": "alice" },

2210 "mode": "form",

2211 "elicitation_id": "elicit-123"

2212}

2213```

2214 

2215#### ElicitationResult output

2216 

2217To override the user's response, return a JSON object with `hookSpecificOutput`:

2218 

2219```json theme={null}

2220{

2221 "hookSpecificOutput": {

2222 "hookEventName": "ElicitationResult",

2223 "action": "decline",

2224 "content": {}

2225 }

2226}

2227```

2228 

2229| Field | Values | Description |

2230| :-------- | :---------------------------- | :--------------------------------------------------------------------- |

2231| `action` | `accept`, `decline`, `cancel` | Overrides the user's action |

2232| `content` | object | Overrides form field values. Only meaningful when `action` is `accept` |

2233 

2234Exit code 2 blocks the response, changing the effective action to `decline`.

2235 

1139## Prompt-based hooks2236## Prompt-based hooks

1140 2237 

1141In addition to Bash command hooks (`type: "command"`), Claude Code supports prompt-based hooks (`type: "prompt"`) that use an LLM to evaluate whether to allow or block an action. Prompt-based hooks work with the following events: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `UserPromptSubmit`, `Stop`, and `SubagentStop`.2238In addition to command, HTTP, and MCP tool hooks, Claude Code supports prompt-based hooks (`type: "prompt"`) that use an LLM to evaluate whether to allow or block an action, and agent hooks (`type: "agent"`) that spawn an agentic verifier with tool access. Not all events support every hook type.

2239 

2240Events that support all five hook types (`command`, `http`, `mcp_tool`, `prompt`, and `agent`):

2241 

2242* `PermissionRequest`

2243* `PostToolBatch`

2244* `PostToolUse`

2245* `PostToolUseFailure`

2246* `PreToolUse`

2247* `Stop`

2248* `SubagentStop`

2249* `TaskCompleted`

2250* `TaskCreated`

2251* `UserPromptExpansion`

2252* `UserPromptSubmit`

2253 

2254Events that support `command`, `http`, and `mcp_tool` hooks but not `prompt` or `agent`:

2255 

2256* `ConfigChange`

2257* `CwdChanged`

2258* `Elicitation`

2259* `ElicitationResult`

2260* `FileChanged`

2261* `InstructionsLoaded`

2262* `Notification`

2263* `PermissionDenied`

2264* `PostCompact`

2265* `PreCompact`

2266* `SessionEnd`

2267* `StopFailure`

2268* `SubagentStart`

2269* `TeammateIdle`

2270* `WorktreeCreate`

2271* `WorktreeRemove`

2272 

2273`SessionStart` and `Setup` support `command` and `mcp_tool` hooks. They do not support `http`, `prompt`, or `agent` hooks.

1142 2274 

1143### How prompt-based hooks work2275### How prompt-based hooks work

1144 2276 


1218 2350 

1219## Agent-based hooks2351## Agent-based hooks

1220 2352 

2353<Warning>

2354 Agent hooks are experimental. Behavior and configuration may change in future releases. For production workflows, prefer [command hooks](#command-hook-fields).

2355</Warning>

2356 

1221Agent-based hooks (`type: "agent"`) are like prompt-based hooks but with multi-turn tool access. Instead of a single LLM call, an agent hook spawns a subagent that can read files, search code, and inspect the codebase to verify conditions. Agent hooks support the same events as prompt-based hooks.2357Agent-based hooks (`type: "agent"`) are like prompt-based hooks but with multi-turn tool access. Instead of a single LLM call, an agent hook spawns a subagent that can read files, search code, and inspect the codebase to verify conditions. Agent hooks support the same events as prompt-based hooks.

1222 2358 

1223### How agent hooks work2359### How agent hooks work


1302 2438 

1303After the background process exits, if the hook produced a JSON response with a `systemMessage` or `additionalContext` field, that content is delivered to Claude as context on the next conversation turn.2439After the background process exits, if the hook produced a JSON response with a `systemMessage` or `additionalContext` field, that content is delivered to Claude as context on the next conversation turn.

1304 2440 

2441Async hook completion notifications are suppressed by default. To see them, enable verbose mode with `Ctrl+O` or start Claude Code with `--verbose`.

2442 

1305### Example: run tests after file changes2443### Example: run tests after file changes

1306 2444 

1307This hook starts a test suite in the background whenever Claude writes a file, then reports the results back to Claude when the tests finish. Save this script to `.claude/hooks/run-tests-async.sh` in your project and make it executable with `chmod +x`:2445This hook starts a test suite in the background whenever Claude writes a file, then reports the results back to Claude when the tests finish. Save this script to `.claude/hooks/run-tests-async.sh` in your project and make it executable with `chmod +x`:


1358 2496 

1359* Only `type: "command"` hooks support `async`. Prompt-based hooks cannot run asynchronously.2497* Only `type: "command"` hooks support `async`. Prompt-based hooks cannot run asynchronously.

1360* Async hooks cannot block tool calls or return decisions. By the time the hook completes, the triggering action has already proceeded.2498* Async hooks cannot block tool calls or return decisions. By the time the hook completes, the triggering action has already proceeded.

1361* Hook output is delivered on the next conversation turn. If the session is idle, the response waits until the next user interaction.2499* Hook output is delivered on the next conversation turn. If the session is idle, the response waits until the next user interaction. Exception: an `asyncRewake` hook that exits with code 2 wakes Claude immediately even when the session is idle.

1362* Each execution creates a separate background process. There is no deduplication across multiple firings of the same async hook.2500* Each execution creates a separate background process. There is no deduplication across multiple firings of the same async hook.

1363 2501 

1364## Security considerations2502## Security considerations

1365 2503 

1366### Disclaimer2504### Disclaimer

1367 2505 

1368Hooks run with your system user's full permissions.2506Command hooks run with your system user's full permissions.

1369 2507 

1370<Warning>2508<Warning>

1371 Hooks execute shell commands with your full user permissions. They can modify, delete, or access any files your user account can access. Review and test all hook commands before adding them to your configuration.2509 Command hooks execute shell commands with your full user permissions. They can modify, delete, or access any files your user account can access. Review and test all hook commands before adding them to your configuration.

1372</Warning>2510</Warning>

1373 2511 

1374### Security best practices2512### Security best practices


1381* **Use absolute paths**: specify full paths for scripts, using `"$CLAUDE_PROJECT_DIR"` for the project root2519* **Use absolute paths**: specify full paths for scripts, using `"$CLAUDE_PROJECT_DIR"` for the project root

1382* **Skip sensitive files**: avoid `.env`, `.git/`, keys, etc.2520* **Skip sensitive files**: avoid `.env`, `.git/`, keys, etc.

1383 2521 

1384## Debug hooks2522## Windows PowerShell tool

1385 2523 

1386Run `claude --debug` to see hook execution details, including which hooks matched, their exit codes, and output. Toggle verbose mode with `Ctrl+O` to see hook progress in the transcript.2524On Windows, you can run individual hooks in PowerShell by setting `"shell": "powershell"` on a command hook. Hooks spawn PowerShell directly, so this works regardless of whether `CLAUDE_CODE_USE_POWERSHELL_TOOL` is set. Claude Code auto-detects `pwsh.exe` (PowerShell 7+) with a fallback to `powershell.exe` (5.1).

1387 2525 

2526```json theme={null}

2527{

2528 "hooks": {

2529 "PostToolUse": [

2530 {

2531 "matcher": "Write",

2532 "hooks": [

2533 {

2534 "type": "command",

2535 "shell": "powershell",

2536 "command": "Write-Host 'File written'"

2537 }

2538 ]

2539 }

2540 ]

2541 }

2542}

1388```2543```

2544 

2545## Debug hooks

2546 

2547Hook execution details, including which hooks matched, their exit codes, and full stdout and stderr, are written to the debug log file. Start Claude Code with `claude --debug-file <path>` to write the log to a known location, or run `claude --debug` and read the log at `~/.claude/debug/<session-id>.txt`. The `--debug` flag does not print to the terminal.

2548 

2549```text theme={null}

1389[DEBUG] Executing hooks for PostToolUse:Write2550[DEBUG] Executing hooks for PostToolUse:Write

1390[DEBUG] Getting matching hook commands for PostToolUse with query: Write

1391[DEBUG] Found 1 hook matchers in settings

1392[DEBUG] Matched 1 hooks for query "Write"

1393[DEBUG] Found 1 hook commands to execute2551[DEBUG] Found 1 hook commands to execute

1394[DEBUG] Executing hook command: <Your command> with timeout 600000ms2552[DEBUG] Executing hook command: <Your command> with timeout 600000ms

1395[DEBUG] Hook command completed with status 0: <Your stdout>2553[DEBUG] Hook command completed with status 0: <Your stdout>

1396```2554```

1397 2555 

1398For troubleshooting common issues like hooks not firing, infinite Stop hook loops, or configuration errors, see [Limitations and troubleshooting](/en/hooks-guide#limitations-and-troubleshooting) in the guide.2556For more granular hook matching details, set `CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose` to see additional log lines such as hook matcher counts and query matching.

2557 

2558For troubleshooting common issues like hooks not firing, infinite Stop hook loops, or configuration errors, see [Limitations and troubleshooting](/en/hooks-guide#limitations-and-troubleshooting) in the guide. For a broader diagnostic walkthrough covering `/context`, `/doctor`, and settings precedence, see [Debug your config](/en/debug-your-config).

hooks-guide.md +334 −58

Details

18 18 

19## Set up your first hook19## Set up your first hook

20 20 

21The fastest way to create a hook is through the `/hooks` interactive menu in Claude Code. This walkthrough creates a desktop notification hook, so you get alerted whenever Claude is waiting for your input instead of watching the terminal.21To create a hook, add a `hooks` block to a [settings file](#configure-hook-location). This walkthrough creates a desktop notification hook, so you get alerted whenever Claude is waiting for your input instead of watching the terminal.

22 22 

23<Steps>23<Steps>

24 <Step title="Open the hooks menu">24 <Step title="Add the hook to your settings">

25 Type `/hooks` in the Claude Code CLI. You'll see a list of all available hook events, plus an option to disable all hooks. Each event corresponds to a point in Claude's lifecycle where you can run custom code. Select `Notification` to create a hook that fires when Claude needs your attention.25 Open `~/.claude/settings.json` and add a `Notification` hook. The example below uses `osascript` for macOS; see [Get notified when Claude needs input](#get-notified-when-claude-needs-input) for Linux and Windows commands.

26 </Step>

27 

28 <Step title="Configure the matcher">

29 The menu shows a list of matchers, which filter when the hook fires. Set the matcher to `*` to fire on all notification types. You can narrow it later by changing the matcher to a specific value like `permission_prompt` or `idle_prompt`.

30 </Step>

31 

32 <Step title="Add your command">

33 Select `+ Add new hook…`. The menu prompts you for a shell command to run when the event fires. Hooks run any shell command you provide, so you can use your platform's built-in notification tool. Copy the command for your OS:

34 26 

35 <Tabs>27 ```json theme={null}

36 <Tab title="macOS">28 {

37 Uses [`osascript`](https://ss64.com/mac/osascript.html) to trigger a native macOS notification through AppleScript:29 "hooks": {

38 30 "Notification": [

39 ```31 {

40 osascript -e 'display notification "Claude Code needs your attention" with title "Claude Code"'32 "matcher": "",

33 "hooks": [

34 {

35 "type": "command",

36 "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"

37 }

38 ]

39 }

40 ]

41 }

42 }

41 ```43 ```

42 </Tab>

43 44 

44 <Tab title="Linux">45 If your settings file already has a `hooks` key, add `Notification` as a sibling of the existing event keys rather than replacing the whole object. Each event name is a key inside the single `hooks` object:

45 Uses `notify-send`, which is pre-installed on most Linux desktops with a notification daemon:

46 46 

47 ```json theme={null}

48 {

49 "hooks": {

50 "PostToolUse": [

51 {

52 "matcher": "Edit|Write",

53 "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }]

54 }

55 ],

56 "Notification": [

57 {

58 "matcher": "",

59 "hooks": [{ "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'" }]

60 }

61 ]

62 }

63 }

47 ```64 ```

48 notify-send 'Claude Code' 'Claude Code needs your attention'

49 ```

50 </Tab>

51 

52 <Tab title="Windows (PowerShell)">

53 Uses PowerShell to show a native message box through .NET's Windows Forms:

54 65 

55 ```66 You can also ask Claude to write the hook for you by describing what you want in the CLI.

56 powershell.exe -Command "[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')"

57 ```

58 </Tab>

59 </Tabs>

60 </Step>67 </Step>

61 68 

62 <Step title="Choose a storage location">69 <Step title="Verify the configuration">

63 The menu asks where to save the hook configuration. Select `User settings` to store it in `~/.claude/settings.json`, which applies the hook to all your projects. You could also choose `Project settings` to scope it to the current project. See [Configure hook location](#configure-hook-location) for all available scopes.70 Type `/hooks` to open the hooks browser. You'll see a list of all available hook events, with a count next to each event that has hooks configured. Select `Notification` to confirm your new hook appears in the list. Selecting the hook shows its details: the event, matcher, type, source file, and command.

64 </Step>71 </Step>

65 72 

66 <Step title="Test the hook">73 <Step title="Test the hook">


68 </Step>75 </Step>

69</Steps>76</Steps>

70 77 

78<Tip>

79 The `/hooks` menu is read-only. To add, modify, or remove hooks, edit your settings JSON directly or ask Claude to make the change.

80</Tip>

81 

71## What you can automate82## What you can automate

72 83 

73Hooks let you run code at key points in Claude Code's lifecycle: format files after edits, block commands before they execute, send notifications when Claude needs input, inject context at session start, and more. For the full list of hook events, see the [Hooks reference](/en/hooks#hook-lifecycle).84Hooks let you run code at key points in Claude Code's lifecycle: format files after edits, block commands before they execute, send notifications when Claude needs input, inject context at session start, and more. For the full list of hook events, see the [Hooks reference](/en/hooks#hook-lifecycle).


78* [Auto-format code after edits](#auto-format-code-after-edits)89* [Auto-format code after edits](#auto-format-code-after-edits)

79* [Block edits to protected files](#block-edits-to-protected-files)90* [Block edits to protected files](#block-edits-to-protected-files)

80* [Re-inject context after compaction](#re-inject-context-after-compaction)91* [Re-inject context after compaction](#re-inject-context-after-compaction)

92* [Audit configuration changes](#audit-configuration-changes)

93* [Reload environment when directory or files change](#reload-environment-when-directory-or-files-change)

94* [Auto-approve specific permission prompts](#auto-approve-specific-permission-prompts)

81 95 

82### Get notified when Claude needs input96### Get notified when Claude needs input

83 97 

84Get a desktop notification whenever Claude finishes working and needs your input, so you can switch to other tasks without checking the terminal.98Get a desktop notification whenever Claude finishes working and needs your input, so you can switch to other tasks without checking the terminal.

85 99 

86This hook uses the `Notification` event, which fires when Claude is waiting for input or permission. Each tab below uses the platform's native notification command. Add this to `~/.claude/settings.json`, or use the [interactive walkthrough](#set-up-your-first-hook) above to configure it with `/hooks`:100This hook uses the `Notification` event, which fires when Claude is waiting for input or permission. Each tab below uses the platform's native notification command. Add this to `~/.claude/settings.json`:

87 101 

88<Tabs>102<Tabs>

89 <Tab title="macOS">103 <Tab title="macOS">


104 }118 }

105 }119 }

106 ```120 ```

121 

122 <Accordion title="If no notification appears">

123 `osascript` routes notifications through the built-in Script Editor app. If Script Editor doesn't have notification permission, the command fails silently, and macOS won't prompt you to grant it. Run this in Terminal once to make Script Editor appear in your notification settings:

124 

125 ```bash theme={null}

126 osascript -e 'display notification "test"'

127 ```

128 

129 Nothing will appear yet. Open **System Settings > Notifications**, find **Script Editor** in the list, and turn on **Allow Notifications**. Run the command again to confirm the test notification appears.

130 </Accordion>

107 </Tab>131 </Tab>

108 132 

109 <Tab title="Linux">133 <Tab title="Linux">


262 286 

263You can replace the `echo` with any command that produces dynamic output, like `git log --oneline -5` to show recent commits. For injecting context on every session start, consider using [CLAUDE.md](/en/memory) instead. For environment variables, see [`CLAUDE_ENV_FILE`](/en/hooks#persist-environment-variables) in the reference.287You can replace the `echo` with any command that produces dynamic output, like `git log --oneline -5` to show recent commits. For injecting context on every session start, consider using [CLAUDE.md](/en/memory) instead. For environment variables, see [`CLAUDE_ENV_FILE`](/en/hooks#persist-environment-variables) in the reference.

264 288 

289### Audit configuration changes

290 

291Track when settings or skills files change during a session. The `ConfigChange` event fires when an external process or editor modifies a configuration file, so you can log changes for compliance or block unauthorized modifications.

292 

293This example appends each change to an audit log. Add this to `~/.claude/settings.json`:

294 

295```json theme={null}

296{

297 "hooks": {

298 "ConfigChange": [

299 {

300 "matcher": "",

301 "hooks": [

302 {

303 "type": "command",

304 "command": "jq -c '{timestamp: now | todate, source: .source, file: .file_path}' >> ~/claude-config-audit.log"

305 }

306 ]

307 }

308 ]

309 }

310}

311```

312 

313The matcher filters by configuration type: `user_settings`, `project_settings`, `local_settings`, `policy_settings`, or `skills`. To block a change from taking effect, exit with code 2 or return `{"decision": "block"}`. See the [ConfigChange reference](/en/hooks#configchange) for the full input schema.

314 

315### Reload environment when directory or files change

316 

317Some projects set different environment variables depending on which directory you are in. Tools like [direnv](https://direnv.net/) do this automatically in your shell, but Claude's Bash tool does not pick up those changes on its own.

318 

319Pairing a `SessionStart` hook with a `CwdChanged` hook fixes this. `SessionStart` loads the variables for the directory you launch in, and `CwdChanged` reloads them each time Claude changes directory. Both write to `CLAUDE_ENV_FILE`, which Claude Code runs as a script preamble before each Bash command. Add this to `~/.claude/settings.json`:

320 

321```json theme={null}

322{

323 "hooks": {

324 "SessionStart": [

325 {

326 "hooks": [

327 {

328 "type": "command",

329 "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""

330 }

331 ]

332 }

333 ],

334 "CwdChanged": [

335 {

336 "hooks": [

337 {

338 "type": "command",

339 "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""

340 }

341 ]

342 }

343 ]

344 }

345}

346```

347 

348Run `direnv allow` once in each directory that has an `.envrc` so direnv is permitted to load it. If you use devbox or nix instead of direnv, the same pattern works with `devbox shellenv` or `devbox global shellenv` in place of `direnv export bash`.

349 

350To react to specific files instead of every directory change, use `FileChanged` with a `matcher` listing the filenames to watch, separated by `|`. To build the watch list, this value is split into literal filenames rather than evaluated as a regex. See [FileChanged](/en/hooks#filechanged) for how the same value also filters which hook groups run when a file changes. This example watches `.envrc` and `.env` in the working directory:

351 

352```json theme={null}

353{

354 "hooks": {

355 "FileChanged": [

356 {

357 "matcher": ".envrc|.env",

358 "hooks": [

359 {

360 "type": "command",

361 "command": "direnv export bash > \"$CLAUDE_ENV_FILE\""

362 }

363 ]

364 }

365 ]

366 }

367}

368```

369 

370See the [CwdChanged](/en/hooks#cwdchanged) and [FileChanged](/en/hooks#filechanged) reference entries for input schemas, `watchPaths` output, and `CLAUDE_ENV_FILE` details.

371 

372### Auto-approve specific permission prompts

373 

374Skip the approval dialog for tool calls you always allow. This example auto-approves `ExitPlanMode`, the tool Claude calls when it finishes presenting a plan and asks to proceed, so you aren't prompted every time a plan is ready.

375 

376Unlike the exit-code examples above, auto-approval requires your hook to write a JSON decision to stdout. A `PermissionRequest` hook fires when Claude Code is about to show a permission dialog, and returning `"behavior": "allow"` answers it on your behalf.

377 

378The matcher scopes the hook to `ExitPlanMode` only, so no other prompts are affected. Add this to `~/.claude/settings.json`:

379 

380```json theme={null}

381{

382 "hooks": {

383 "PermissionRequest": [

384 {

385 "matcher": "ExitPlanMode",

386 "hooks": [

387 {

388 "type": "command",

389 "command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"

390 }

391 ]

392 }

393 ]

394 }

395}

396```

397 

398When the hook approves, Claude Code exits plan mode and restores whatever permission mode was active before you entered plan mode. The transcript shows "Allowed by PermissionRequest hook" where the dialog would have appeared. The hook path always keeps the current conversation: it cannot clear context and start a fresh implementation session the way the dialog can.

399 

400To set a specific permission mode instead, your hook's output can include an `updatedPermissions` array with a `setMode` entry. The `mode` value is any permission mode like `default`, `acceptEdits`, or `bypassPermissions`, and `destination: "session"` applies it for the current session only.

401 

402<Note>

403 `bypassPermissions` only applies if the session was launched with bypass mode already available: `--dangerously-skip-permissions`, `--permission-mode bypassPermissions`, `--allow-dangerously-skip-permissions`, or `permissions.defaultMode: "bypassPermissions"` in settings, and not disabled by [`permissions.disableBypassPermissionsMode`](/en/permissions#managed-settings). It is never persisted as `defaultMode`.

404</Note>

405 

406To switch the session to `acceptEdits`, your hook writes this JSON to stdout:

407 

408```json theme={null}

409{

410 "hookSpecificOutput": {

411 "hookEventName": "PermissionRequest",

412 "decision": {

413 "behavior": "allow",

414 "updatedPermissions": [

415 { "type": "setMode", "mode": "acceptEdits", "destination": "session" }

416 ]

417 }

418 }

419}

420```

421 

422Keep the matcher as narrow as possible. Matching on `.*` or leaving the matcher empty would auto-approve every permission prompt, including file writes and shell commands. See the [PermissionRequest reference](/en/hooks#permissionrequest-decision-control) for the full set of decision fields.

423 

265## How hooks work424## How hooks work

266 425 

267Hook events fire at specific lifecycle points in Claude Code. When an event fires, all matching hooks run in parallel, and identical hook commands are automatically deduplicated. The table below shows each event and when it triggers:426Hook events fire at specific lifecycle points in Claude Code. When an event fires, all matching hooks run in parallel, and identical hook commands are automatically deduplicated. The table below shows each event and when it triggers:

268 427 

269| Event | When it fires |428| Event | When it fires |

270| :------------------- | :--------------------------------------------------- |429| :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- |

271| `SessionStart` | When a session begins or resumes |430| `SessionStart` | When a session begins or resumes |

272| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |431| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |

432| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |

273| `PreToolUse` | Before a tool call executes. Can block it |433| `PreToolUse` | Before a tool call executes. Can block it |

274| `PermissionRequest` | When a permission dialog appears |434| `PermissionRequest` | When a permission dialog appears |

435| `PermissionDenied` | When a tool call is denied by the auto mode classifier. Return `{retry: true}` to tell the model it may retry the denied tool call |

275| `PostToolUse` | After a tool call succeeds |436| `PostToolUse` | After a tool call succeeds |

276| `PostToolUseFailure` | After a tool call fails |437| `PostToolUseFailure` | After a tool call fails |

438| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |

277| `Notification` | When Claude Code sends a notification |439| `Notification` | When Claude Code sends a notification |

278| `SubagentStart` | When a subagent is spawned |440| `SubagentStart` | When a subagent is spawned |

279| `SubagentStop` | When a subagent finishes |441| `SubagentStop` | When a subagent finishes |

442| `TaskCreated` | When a task is being created via `TaskCreate` |

443| `TaskCompleted` | When a task is being marked as completed |

280| `Stop` | When Claude finishes responding |444| `Stop` | When Claude finishes responding |

445| `StopFailure` | When the turn ends due to an API error. Output and exit code are ignored |

446| `TeammateIdle` | When an [agent team](/en/agent-teams) teammate is about to go idle |

447| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |

448| `ConfigChange` | When a configuration file changes during a session |

449| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |

450| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |

451| `WorktreeCreate` | When a worktree is being created via `--worktree` or `isolation: "worktree"`. Replaces default git behavior |

452| `WorktreeRemove` | When a worktree is being removed, either at session exit or when a subagent finishes |

281| `PreCompact` | Before context compaction |453| `PreCompact` | Before context compaction |

454| `PostCompact` | After context compaction completes |

455| `Elicitation` | When an MCP server requests user input during a tool call |

456| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |

282| `SessionEnd` | When a session terminates |457| `SessionEnd` | When a session terminates |

283 458 

284Each hook has a `type` that determines how it runs. Most hooks use `"type": "command"`, which runs a shell command. Two other options use a Claude model to make decisions: `"type": "prompt"` for single-turn evaluation and `"type": "agent"` for multi-turn verification with tool access. See [Prompt-based hooks](#prompt-based-hooks) and [Agent-based hooks](#agent-based-hooks) for details.459When multiple hooks match, each one returns its own result. For decisions, Claude Code picks the most restrictive answer. A `PreToolUse` hook returning `deny` cancels the tool call no matter what the others return. One hook returning `ask` forces the permission prompt even if the rest return `allow`. Text from `additionalContext` is kept from every hook and passed to Claude together.

460 

461Each hook has a `type` that determines how it runs. Most hooks use `"type": "command"`, which runs a shell command. Four other types are available:

462 

463* `"type": "http"`: POST event data to a URL. See [HTTP hooks](#http-hooks).

464* `"type": "mcp_tool"`: call a tool on an already-connected MCP server. See [MCP tool hooks](/en/hooks#mcp-tool-hook-fields).

465* `"type": "prompt"`: single-turn LLM evaluation. See [Prompt-based hooks](#prompt-based-hooks).

466* `"type": "agent"`: multi-turn verification with tool access. Agent hooks are experimental and may change. See [Agent-based hooks](#agent-based-hooks).

285 467 

286### Read input and return output468### Read input and return output

287 469 


303}485}

304```486```

305 487 

306Your script can parse that JSON and act on any of those fields. `UserPromptSubmit` hooks get the `prompt` text instead, `SessionStart` hooks get the `source` (startup, resume, compact), and so on. See [Common input fields](/en/hooks#common-input-fields) in the reference for shared fields, and each event's section for event-specific schemas.488Your script can parse that JSON and act on any of those fields. `UserPromptSubmit` hooks get the `prompt` text instead, `SessionStart` hooks get the `source` (startup, resume, clear, compact), and so on. See [Common input fields](/en/hooks#common-input-fields) in the reference for shared fields, and each event's section for event-specific schemas.

307 489 

308#### Hook output490#### Hook output

309 491 


324 506 

325The exit code determines what happens next:507The exit code determines what happens next:

326 508 

327* **Exit 0**: the action proceeds. For `UserPromptSubmit` and `SessionStart` hooks, anything you write to stdout is added to Claude's context.509* **Exit 0**: the action proceeds. For `UserPromptSubmit`, `UserPromptExpansion`, and `SessionStart` hooks, anything you write to stdout is added to Claude's context.

328* **Exit 2**: the action is blocked. Write a reason to stderr, and Claude receives it as feedback so it can adjust.510* **Exit 2**: the action is blocked. Write a reason to stderr, and Claude receives it as feedback so it can adjust.

329* **Any other exit code**: the action proceeds. Stderr is logged but not shown to Claude. Toggle verbose mode with `Ctrl+O` to see these messages in the transcript.511* **Any other exit code**: the action proceeds. The transcript shows a `<hook name> hook error` notice followed by the first line of stderr; the full stderr goes to the [debug log](/en/hooks#debug-hooks).

330 512 

331#### Structured JSON output513#### Structured JSON output

332 514 


348}530}

349```531```

350 532 

351Claude Code reads `permissionDecision` and cancels the tool call, then feeds `permissionDecisionReason` back to Claude as feedback. The three options are:533With `"deny"`, Claude Code cancels the tool call and feeds `permissionDecisionReason` back to Claude. These `permissionDecision` values are specific to `PreToolUse`:

352 534 

353* `"allow"`: proceed without showing a permission prompt535* `"allow"`: skip the interactive permission prompt. Deny and ask rules, including enterprise managed deny lists, still apply

354* `"deny"`: cancel the tool call and send the reason to Claude536* `"deny"`: cancel the tool call and send the reason to Claude

355* `"ask"`: show the permission prompt to the user as normal537* `"ask"`: show the permission prompt to the user as normal

356 538 

357For `UserPromptSubmit` hooks, use `additionalContext` instead to inject text into Claude's context. See [Control behavior with JSON output](/en/hooks#json-output) in the reference for the full JSON schema. Prompt-based hooks (`type: "prompt"`) handle output differently: see [Prompt-based hooks](#prompt-based-hooks).539A fourth value, `"defer"`, is available in [non-interactive mode](/en/headless) with the `-p` flag. It exits the process with the tool call preserved so an Agent SDK wrapper can collect input and resume. See [Defer a tool call for later](/en/hooks#defer-a-tool-call-for-later) in the reference.

540 

541Returning `"allow"` skips the interactive prompt but does not override [permission rules](/en/permissions#manage-permissions). If a deny rule matches the tool call, the call is blocked even when your hook returns `"allow"`. If an ask rule matches, the user is still prompted. This means deny rules from any settings scope, including [managed settings](/en/settings#settings-files), always take precedence over hook approvals.

542 

543Other events use different decision patterns. For example, `PostToolUse` and `Stop` hooks use a top-level `decision: "block"` field, while `PermissionRequest` uses `hookSpecificOutput.decision.behavior`. See the [summary table](/en/hooks#decision-control) in the reference for a full breakdown by event.

544 

545For `UserPromptSubmit` hooks, use `additionalContext` instead to inject text into Claude's context. Prompt-based hooks (`type: "prompt"`) handle output differently: see [Prompt-based hooks](#prompt-based-hooks).

358 546 

359### Filter hooks with matchers547### Filter hooks with matchers

360 548 


375}563}

376```564```

377 565 

378The `"Edit|Write"` matcher is a regex pattern that matches the tool name. The hook only fires when Claude uses the `Edit` or `Write` tool, not when it uses `Bash`, `Read`, or any other tool.566The `"Edit|Write"` matcher fires only when Claude uses the `Edit` or `Write` tool, not when it uses `Bash`, `Read`, or any other tool. See [Matcher patterns](/en/hooks#matcher-patterns) for how plain names and regular expressions are evaluated.

379 567 

380Each event type matches on a specific field. Matchers support exact strings and regex patterns:568Each event type matches on a specific field:

381 569 

382| Event | What the matcher filters | Example matcher values |570| Event | What the matcher filters | Example matcher values |

383| :--------------------------------------------------------------------- | :------------------------ | :----------------------------------------------------------------------- |571| :-------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ |

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

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

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

387| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |575| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |

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

389| `PreCompact` | what triggered compaction | `manual`, `auto` |577| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |

390| `UserPromptSubmit`, `Stop` | no matcher support | always fires on every occurrence |

391| `SubagentStop` | agent type | same values as `SubagentStart` |578| `SubagentStop` | agent type | same values as `SubagentStart` |

579| `ConfigChange` | configuration source | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |

580| `StopFailure` | error type | `rate_limit`, `authentication_failed`, `billing_error`, `invalid_request`, `server_error`, `max_output_tokens`, `unknown` |

581| `InstructionsLoaded` | load reason | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |

582| `Elicitation` | MCP server name | your configured MCP server names |

583| `ElicitationResult` | MCP server name | same values as `Elicitation` |

584| `FileChanged` | literal filenames to watch (see [FileChanged](/en/hooks#filechanged)) | `.envrc\|.env` |

585| `UserPromptExpansion` | command name | your skill or command names |

586| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `CwdChanged` | no matcher support | always fires on every occurrence |

392 587 

393A few more examples showing matchers on different event types:588A few more examples showing matchers on different event types:

394 589 


418 <Tab title="Match MCP tools">613 <Tab title="Match MCP tools">

419 MCP tools use a different naming convention than built-in tools: `mcp__<server>__<tool>`, where `<server>` is the MCP server name and `<tool>` is the tool it provides. For example, `mcp__github__search_repositories` or `mcp__filesystem__read_file`. Use a regex matcher to target all tools from a specific server, or match across servers with a pattern like `mcp__.*__write.*`. See [Match MCP tools](/en/hooks#match-mcp-tools) in the reference for the full list of examples.614 MCP tools use a different naming convention than built-in tools: `mcp__<server>__<tool>`, where `<server>` is the MCP server name and `<tool>` is the tool it provides. For example, `mcp__github__search_repositories` or `mcp__filesystem__read_file`. Use a regex matcher to target all tools from a specific server, or match across servers with a pattern like `mcp__.*__write.*`. See [Match MCP tools](/en/hooks#match-mcp-tools) in the reference for the full list of examples.

420 615 

421 The command below extracts the tool name from the hook's JSON input with `jq` and writes it to stderr, where it shows up in verbose mode (`Ctrl+O`):616 The command below extracts the tool name from the hook's JSON input with `jq` and writes it to stderr. Writing to stderr keeps stdout clean for JSON output and sends the message to the [debug log](/en/hooks#debug-hooks):

422 617 

423 ```json theme={null}618 ```json theme={null}

424 {619 {


464 659 

465For full matcher syntax, see the [Hooks reference](/en/hooks#configuration).660For full matcher syntax, see the [Hooks reference](/en/hooks#configuration).

466 661 

662#### Filter by tool name and arguments with the `if` field

663 

664<Note>

665 The `if` field requires Claude Code v2.1.85 or later. Earlier versions ignore it and run the hook on every matched call.

666</Note>

667 

668The `if` field uses [permission rule syntax](/en/permissions) to filter hooks by tool name and arguments together, so the hook process only spawns when the tool call matches, or when a Bash command is too complex to parse. This goes beyond `matcher`, which filters at the group level by tool name only.

669 

670For example, to run a hook only when Claude uses `git` commands rather than all Bash commands:

671 

672```json theme={null}

673{

674 "hooks": {

675 "PreToolUse": [

676 {

677 "matcher": "Bash",

678 "hooks": [

679 {

680 "type": "command",

681 "if": "Bash(git *)",

682 "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-git-policy.sh"

683 }

684 ]

685 }

686 ]

687 }

688}

689```

690 

691The hook process only spawns when a subcommand of the Bash command matches `git *`, or when the command is too complex to parse into subcommands. For compound commands like `npm test && git push`, Claude Code evaluates each subcommand and fires the hook because `git push` matches. The `if` field accepts the same patterns as permission rules: `"Bash(git *)"`, `"Edit(*.ts)"`, and so on. To match multiple tool names, use separate handlers each with its own `if` value, or match at the `matcher` level where pipe alternation is supported.

692 

693`if` only works on tool events: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, and `PermissionDenied`. Adding it to any other event prevents the hook from running.

694 

467### Configure hook location695### Configure hook location

468 696 

469Where you add a hook determines its scope:697Where you add a hook determines its scope:


477| [Plugin](/en/plugins) `hooks/hooks.json` | When plugin is enabled | Yes, bundled with the plugin |705| [Plugin](/en/plugins) `hooks/hooks.json` | When plugin is enabled | Yes, bundled with the plugin |

478| [Skill](/en/skills) or [agent](/en/sub-agents) frontmatter | While the skill or agent is active | Yes, defined in the component file |706| [Skill](/en/skills) or [agent](/en/sub-agents) frontmatter | While the skill or agent is active | Yes, defined in the component file |

479 707 

480You can also use the [`/hooks` menu](/en/hooks#the-hooks-menu) in Claude Code to add, delete, and view hooks interactively. To disable all hooks at once, use the toggle at the bottom of the `/hooks` menu or set `"disableAllHooks": true` in your settings file.708Run [`/hooks`](/en/hooks#the-hooks-menu) in Claude Code to browse all configured hooks grouped by event. To disable all hooks at once, set `"disableAllHooks": true` in your settings file.

481 709 

482Hooks added through the `/hooks` menu take effect immediately. If you edit settings files directly while Claude Code is running, the changes won't take effect until you review them in the `/hooks` menu or restart your session.710If you edit settings files directly while Claude Code is running, the file watcher normally picks up hook changes automatically.

483 711 

484## Prompt-based hooks712## Prompt-based hooks

485 713 


513 741 

514## Agent-based hooks742## Agent-based hooks

515 743 

744<Warning>

745 Agent hooks are experimental. Behavior and configuration may change in future releases. For production workflows, prefer [command hooks](/en/hooks#command-hook-fields).

746</Warning>

747 

516When verification requires inspecting files or running commands, use `type: "agent"` hooks. Unlike prompt hooks which make a single LLM call, agent hooks spawn a subagent that can read files, search code, and use other tools to verify conditions before returning a decision.748When verification requires inspecting files or running commands, use `type: "agent"` hooks. Unlike prompt hooks which make a single LLM call, agent hooks spawn a subagent that can read files, search code, and use other tools to verify conditions before returning a decision.

517 749 

518Agent hooks use the same `"ok"` / `"reason"` response format as prompt hooks, but with a longer default timeout of 60 seconds and up to 50 tool-use turns.750Agent hooks use the same `"ok"` / `"reason"` response format as prompt hooks, but with a longer default timeout of 60 seconds and up to 50 tool-use turns.


541 773 

542For full configuration options, see [Agent-based hooks](/en/hooks#agent-based-hooks) in the reference.774For full configuration options, see [Agent-based hooks](/en/hooks#agent-based-hooks) in the reference.

543 775 

776## HTTP hooks

777 

778Use `type: "http"` hooks to POST event data to an HTTP endpoint instead of running a shell command. The endpoint receives the same JSON that a command hook would receive on stdin, and returns results through the HTTP response body using the same JSON format.

779 

780HTTP hooks are useful when you want a web server, cloud function, or external service to handle hook logic: for example, a shared audit service that logs tool use events across a team.

781 

782This example posts every tool use to a local logging service:

783 

784```json theme={null}

785{

786 "hooks": {

787 "PostToolUse": [

788 {

789 "hooks": [

790 {

791 "type": "http",

792 "url": "http://localhost:8080/hooks/tool-use",

793 "headers": {

794 "Authorization": "Bearer $MY_TOKEN"

795 },

796 "allowedEnvVars": ["MY_TOKEN"]

797 }

798 ]

799 }

800 ]

801 }

802}

803```

804 

805The endpoint should return a JSON response body using the same [output format](/en/hooks#json-output) as command hooks. To block a tool call, return a 2xx response with the appropriate `hookSpecificOutput` fields. HTTP status codes alone cannot block actions.

806 

807Header values support environment variable interpolation using `$VAR_NAME` or `${VAR_NAME}` syntax. Only variables listed in the `allowedEnvVars` array are resolved; all other `$VAR` references remain empty.

808 

809For full configuration options and response handling, see [HTTP hooks](/en/hooks#http-hook-fields) in the reference.

810 

544## Limitations and troubleshooting811## Limitations and troubleshooting

545 812 

546### Limitations813### Limitations

547 814 

548* Hooks communicate through stdout, stderr, and exit codes only. They cannot trigger slash commands or tool calls directly.815* Command hooks communicate through stdout, stderr, and exit codes only. They cannot trigger `/` commands or tool calls. Text returned via `additionalContext` is injected as a system reminder that Claude reads as plain text. HTTP hooks communicate through the response body instead.

549* Hook timeout is 10 minutes by default, configurable per hook with the `timeout` field (in seconds).816* Hook timeout is 10 minutes by default, configurable per hook with the `timeout` field (in seconds).

550* `PostToolUse` hooks cannot undo actions since the tool has already executed.817* `PostToolUse` hooks cannot undo actions since the tool has already executed.

551* `PermissionRequest` hooks do not fire in [non-interactive mode](/en/headless) (`-p`). Use `PreToolUse` hooks for automated permission decisions.818* `PermissionRequest` hooks do not fire in [non-interactive mode](/en/headless) (`-p`). Use `PreToolUse` hooks for automated permission decisions.

552* `Stop` hooks fire whenever Claude finishes responding, not only at task completion. They do not fire on user interrupts.819* `Stop` hooks fire whenever Claude finishes responding, not only at task completion. They do not fire on user interrupts. API errors fire [StopFailure](/en/hooks#stopfailure) instead.

820* When multiple PreToolUse hooks return [`updatedInput`](/en/hooks#pretooluse) to rewrite a tool's arguments, the last one to finish wins. Since hooks run in parallel, the order is non-deterministic. Avoid having more than one hook modify the same tool's input.

821 

822### Hooks and permission modes

823 

824PreToolUse hooks fire before any permission-mode check. A hook that returns `permissionDecision: "deny"` blocks the tool even in `bypassPermissions` mode or with `--dangerously-skip-permissions`. This lets you enforce policy that users cannot bypass by changing their permission mode.

825 

826The reverse is not true: a hook returning `"allow"` does not bypass deny rules from settings. Hooks can tighten restrictions but not loosen them past what permission rules allow.

553 827 

554### Hook not firing828### Hook not firing

555 829 


577 851 

578You edited a settings file but the hooks don't appear in the menu.852You edited a settings file but the hooks don't appear in the menu.

579 853 

580* Restart your session or open `/hooks` to reload. Hooks added through the `/hooks` menu take effect immediately, but manual file edits require a reload.854* File edits are normally picked up automatically. If they haven't appeared after a few seconds, the file watcher may have missed the change: restart your session to force a reload.

581* Verify your JSON is valid (trailing commas and comments are not allowed)855* Verify your JSON is valid (trailing commas and comments are not allowed)

582* Confirm the settings file is in the correct location: `.claude/settings.json` for project hooks, `~/.claude/settings.json` for global hooks856* Confirm the settings file is in the correct location: `.claude/settings.json` for project hooks, `~/.claude/settings.json` for global hooks

583 857 


602 876 

603When Claude Code runs a hook, it spawns a shell that sources your profile (`~/.zshrc` or `~/.bashrc`). If your profile contains unconditional `echo` statements, that output gets prepended to your hook's JSON:877When Claude Code runs a hook, it spawns a shell that sources your profile (`~/.zshrc` or `~/.bashrc`). If your profile contains unconditional `echo` statements, that output gets prepended to your hook's JSON:

604 878 

605```879```text theme={null}

606Shell ready on arm64880Shell ready on arm64

607{"decision": "allow"}881{"decision": "block", "reason": "Not allowed"}

608```882```

609 883 

610Claude Code tries to parse this as JSON and fails. To fix this, wrap echo statements in your shell profile so they only run in interactive shells:884Claude Code tries to parse this as JSON and fails. To fix this, wrap echo statements in your shell profile so they only run in interactive shells:


620 894 

621### Debug techniques895### Debug techniques

622 896 

623Toggle verbose mode with `Ctrl+O` to see hook output in the transcript, or run `claude --debug` for full execution details including which hooks matched and their exit codes.897The transcript view, toggled with `Ctrl+O`, shows a one-line summary for each hook that fired: success is silent, blocking errors show stderr, and non-blocking errors show a `<hook name> hook error` notice followed by the first line of stderr.

898 

899For full execution details including which hooks matched, their exit codes, stdout, and stderr, read the debug log. Start Claude Code with `claude --debug-file /tmp/claude.log` to write to a known path, then `tail -f /tmp/claude.log` in another terminal. If you started without that flag, run `/debug` mid-session to enable logging and find the log path.

624 900 

625## Learn more901## Learn more

626 902 

Details

14 14 

15When you give Claude a task, it works through three phases: **gather context**, **take action**, and **verify results**. These phases blend together. Claude uses tools throughout, whether searching files to understand your code, editing to make changes, or running tests to check its work.15When you give Claude a task, it works through three phases: **gather context**, **take action**, and **verify results**. These phases blend together. Claude uses tools throughout, whether searching files to understand your code, editing to make changes, or running tests to check its work.

16 16 

17<img src="https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/agentic-loop.svg?fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=e30acfc80d6ff01ec877dd19c7af58b2" alt="The agentic loop: Your prompt leads to Claude gathering context, taking action, verifying results, and repeating until task complete. You can interrupt at any point." data-og-width="720" width="720" data-og-height="280" height="280" data-path="images/agentic-loop.svg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/agentic-loop.svg?w=280&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=8620f6ebce761a1e8bbf7f0a0255cc15 280w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/agentic-loop.svg?w=560&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=7b46b5ff4454aa4a03725eee625b39a0 560w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/agentic-loop.svg?w=840&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=7fa0397bc37d147e3bf3bb6296c6477f 840w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/agentic-loop.svg?w=1100&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=73b2a7040c4c93821c4d5bbee9f4a2d4 1100w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/agentic-loop.svg?w=1650&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=17703cbeb6f59b40a00ab24f56d5f8f9 1650w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/agentic-loop.svg?w=2500&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=20dedb60b95d45a1bd60a0cccaf3e1ff 2500w" />17<img src="https://mintcdn.com/claude-code/c5r9_6tjPMzFdDDT/images/agentic-loop.svg?fit=max&auto=format&n=c5r9_6tjPMzFdDDT&q=85&s=5f1827dec8539f38adee90ead3a85a38" alt="The agentic loop: Your prompt leads to Claude gathering context, taking action, verifying results, and repeating until task complete. You can interrupt at any point." width="720" height="280" data-path="images/agentic-loop.svg" />

18 18 

19The loop adapts to what you ask. A question about your codebase might only need context gathering. A bug fix cycles through all three phases repeatedly. A refactor might involve extensive verification. Claude decides what each step requires based on what it learned from the previous step, chaining dozens of actions together and course-correcting along the way.19The loop adapts to what you ask. A question about your codebase might only need context gathering. A bug fix cycles through all three phases repeatedly. A refactor might involve extensive verification. Claude decides what each step requires based on what it learned from the previous step, chaining dozens of actions together and course-correcting along the way.

20 20 


34 34 

35Tools are what make Claude Code agentic. Without tools, Claude can only respond with text. With tools, Claude can act: read your code, edit files, run commands, search the web, and interact with external services. Each tool use returns information that feeds back into the loop, informing Claude's next decision.35Tools are what make Claude Code agentic. Without tools, Claude can only respond with text. With tools, Claude can act: read your code, edit files, run commands, search the web, and interact with external services. Each tool use returns information that feeds back into the loop, informing Claude's next decision.

36 36 

37The built-in tools generally fall into four categories, each representing a different kind of agency.37The built-in tools generally fall into five categories, each representing a different kind of agency.

38 38 

39| Category | What Claude can do |39| Category | What Claude can do |

40| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |40| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |


44| **Web** | Search the web, fetch documentation, look up error messages |44| **Web** | Search the web, fetch documentation, look up error messages |

45| **Code intelligence** | See type errors and warnings after edits, jump to definitions, find references (requires [code intelligence plugins](/en/discover-plugins#code-intelligence)) |45| **Code intelligence** | See type errors and warnings after edits, jump to definitions, find references (requires [code intelligence plugins](/en/discover-plugins#code-intelligence)) |

46 46 

47These are the primary capabilities. Claude also has tools for spawning subagents, asking you questions, and other orchestration tasks. See [Tools available to Claude](/en/settings#tools-available-to-claude) for the complete list.47These are the primary capabilities. Claude also has tools for spawning subagents, asking you questions, and other orchestration tasks. See [Tools available to Claude](/en/tools-reference) for the complete list.

48 48 

49Claude chooses which tools to use based on your prompt and what it learns along the way. When you say "fix the failing tests," Claude might:49Claude chooses which tools to use based on your prompt and what it learns along the way. When you say "fix the failing tests," Claude might:

50 50 


61 61 

62## What Claude can access62## What Claude can access

63 63 

64This guide focuses on the terminal. Claude Code also runs in [VS Code, JetBrains IDEs, and other environments](/en/ide-integrations).64This guide focuses on the terminal. Claude Code also runs in [VS Code](/en/vs-code), [JetBrains IDEs](/en/jetbrains), and other environments.

65 65 

66When you run `claude` in a directory, Claude Code gains access to:66When you run `claude` in a directory, Claude Code gains access to:

67 67 


69* **Your terminal.** Any command you could run: build tools, git, package managers, system utilities, scripts. If you can do it from the command line, Claude can too.69* **Your terminal.** Any command you could run: build tools, git, package managers, system utilities, scripts. If you can do it from the command line, Claude can too.

70* **Your git state.** Current branch, uncommitted changes, and recent commit history.70* **Your git state.** Current branch, uncommitted changes, and recent commit history.

71* **Your [CLAUDE.md](/en/memory).** A markdown file where you store project-specific instructions, conventions, and context that Claude should know every session.71* **Your [CLAUDE.md](/en/memory).** A markdown file where you store project-specific instructions, conventions, and context that Claude should know every session.

72* **[Auto memory](/en/memory#auto-memory).** Learnings Claude saves automatically as you work, like project patterns and your preferences. The first 200 lines or 25KB of MEMORY.md, whichever comes first, load at the start of each session.

72* **Extensions you configure.** [MCP servers](/en/mcp) for external services, [skills](/en/skills) for workflows, [subagents](/en/sub-agents) for delegated work, and [Claude in Chrome](/en/chrome) for browser interaction.73* **Extensions you configure.** [MCP servers](/en/mcp) for external services, [skills](/en/skills) for workflows, [subagents](/en/sub-agents) for delegated work, and [Claude in Chrome](/en/chrome) for browser interaction.

73 74 

74Because Claude sees your whole project, it can work across it. When you ask Claude to "fix the authentication bug," it searches for relevant files, reads multiple files to understand context, makes coordinated edits across them, runs tests to verify the fix, and commits the changes if you ask. This is different from inline code assistants that only see the current file.75Because Claude sees your whole project, it can work across it. When you ask Claude to "fix the authentication bug," it searches for relevant files, reads multiple files to understand context, makes coordinated edits across them, runs tests to verify the fix, and commits the changes if you ask. This is different from inline code assistants that only see the current file.

75 76 

77## Environments and interfaces

78 

79The agentic loop, tools, and capabilities described above are the same everywhere you use Claude Code. What changes is where the code executes and how you interact with it.

80 

81### Execution environments

82 

83Claude Code runs in three environments, each with different tradeoffs for where your code executes.

84 

85| Environment | Where code runs | Use case |

86| ------------------ | --------------------------------------- | ---------------------------------------------------------- |

87| **Local** | Your machine | Default. Full access to your files, tools, and environment |

88| **Cloud** | Anthropic-managed VMs | Offload tasks, work on repos you don't have locally |

89| **Remote Control** | Your machine, controlled from a browser | Use the web UI while keeping everything local |

90 

91### Interfaces

92 

93You can access Claude Code through the terminal, the [desktop app](/en/desktop), [IDE extensions](/en/vs-code), [claude.ai/code](https://claude.ai/code), [Remote Control](/en/remote-control), [Slack](/en/slack), and [CI/CD pipelines](/en/github-actions). The interface determines how you see and interact with Claude, but the underlying agentic loop is identical. See [Use Claude Code everywhere](/en/overview#use-claude-code-everywhere) for the full list.

94 

76## Work with sessions95## Work with sessions

77 96 

78Claude Code saves your conversation locally as you work. Each message, tool use, and result is stored, which enables [rewinding](#undo-changes-with-checkpoints), [resuming, and forking](#resume-or-fork-sessions) sessions. Before Claude makes code changes, it also snapshots the affected files so you can revert if needed.97Claude Code saves your conversation locally as you work. Each message, tool use, and result is written to a plaintext JSONL file under `~/.claude/projects/`, which enables [rewinding](#undo-changes-with-checkpoints), [resuming, and forking](#resume-or-fork-sessions) sessions. Before Claude makes code changes, it also snapshots the affected files so you can revert if needed. For paths, retention, and how to clear this data, see [application data in `~/.claude`](/en/claude-directory#application-data).

79 98 

80**Sessions are ephemeral.** Unlike claude.ai, Claude Code has no persistent memory between sessions. Each new session starts fresh. Claude doesn't "learn" your preferences over time or remember what you worked on last week. If you want Claude to know something across sessions, put it in your [CLAUDE.md](/en/memory).99**Sessions are independent.** Each new session starts with a fresh context window, without the conversation history from previous sessions. Claude can persist learnings across sessions using [auto memory](/en/memory#auto-memory), and you can add your own persistent instructions in [CLAUDE.md](/en/memory).

81 100 

82### Work across branches101### Work across branches

83 102 

84Each Claude Code conversation is a session tied to your current directory. When you resume, you only see sessions from that directory.103Each Claude Code conversation is a session tied to your current directory. The `/resume` picker shows sessions from the current worktree by default, with keyboard shortcuts to widen the list to other worktrees or projects. See [Resume previous conversations](/en/common-workflows#resume-previous-conversations) for the full list of picker shortcuts and how name resolution works.

85 104 

86Claude sees your current branch's files. When you switch branches, Claude sees the new branch's files, but your conversation history stays the same. Claude remembers what you discussed even after switching.105Claude sees your current branch's files. When you switch branches, Claude sees the new branch's files, but your conversation history stays the same. Claude remembers what you discussed even after switching.

87 106 


91 110 

92When you resume a session with `claude --continue` or `claude --resume`, you pick up where you left off using the same session ID. New messages append to the existing conversation. Your full conversation history is restored, but session-scoped permissions are not. You'll need to re-approve those.111When you resume a session with `claude --continue` or `claude --resume`, you pick up where you left off using the same session ID. New messages append to the existing conversation. Your full conversation history is restored, but session-scoped permissions are not. You'll need to re-approve those.

93 112 

94<img src="https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/session-continuity.svg?fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=f671b603cc856119c95475b9084ebfef" alt="Session continuity: resume continues the same session, fork creates a new branch with a new ID." data-og-width="560" width="560" data-og-height="280" height="280" data-path="images/session-continuity.svg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/session-continuity.svg?w=280&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=bddf1f33d419a27d7427acdf06058804 280w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/session-continuity.svg?w=560&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=417478eb9b86003b8eebaac058a8618a 560w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/session-continuity.svg?w=840&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=1d89d26e2c0487f067d187c3fa5f7170 840w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/session-continuity.svg?w=1100&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=8ea739a1f7860e4edbbcf74d444e37b2 1100w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/session-continuity.svg?w=1650&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=9cb5095d6a8920f04c3b78d31a69c809 1650w, https://mintcdn.com/claude-code/ELkJZG54dIaeldDC/images/session-continuity.svg?w=2500&fit=max&auto=format&n=ELkJZG54dIaeldDC&q=85&s=d67e1744e4878813d20c6c3f39d9459d 2500w" />113<img src="https://mintcdn.com/claude-code/c5r9_6tjPMzFdDDT/images/session-continuity.svg?fit=max&auto=format&n=c5r9_6tjPMzFdDDT&q=85&s=fa41d12bfb57579cabfeece907151d30" alt="Session continuity: resume continues the same session, fork creates a new branch with a new ID." width="560" height="280" data-path="images/session-continuity.svg" />

95 114 

96To branch off and try a different approach without affecting the original session, use the `--fork-session` flag:115To branch off and try a different approach without affecting the original session, use the `--fork-session` flag:

97 116 


105 124 

106### The context window125### The context window

107 126 

108Claude's context window holds your conversation history, file contents, command outputs, [CLAUDE.md](/en/memory), loaded skills, and system instructions. As you work, context fills up. Claude compacts automatically, but instructions from early in the conversation can get lost. Put persistent rules in CLAUDE.md, and run `/context` to see what's using space.127Claude's context window holds your conversation history, file contents, command outputs, [CLAUDE.md](/en/memory), [auto memory](/en/memory#auto-memory), loaded skills, and system instructions. As you work, context fills up. Claude compacts automatically, but instructions from early in the conversation can get lost. Put persistent rules in CLAUDE.md, and run `/context` to see what's using space.

128 

129For an interactive walkthrough of what loads and when, see [Explore the context window](/en/context-window).

109 130 

110#### When context fills up131#### When context fills up

111 132 


113 134 

114To control what's preserved during compaction, add a "Compact Instructions" section to CLAUDE.md or run `/compact` with a focus (like `/compact focus on the API changes`).135To control what's preserved during compaction, add a "Compact Instructions" section to CLAUDE.md or run `/compact` with a focus (like `/compact focus on the API changes`).

115 136 

116Run `/context` to see what's using space. MCP servers add tool definitions to every request, so a few servers can consume significant context before you start working. Run `/mcp` to check per-server costs.137If a single file or tool output is so large that context refills immediately after each summary, Claude Code stops auto-compacting after a few attempts and shows an error instead of looping. See [Auto-compaction stops with a thrashing error](/en/troubleshooting#auto-compaction-stops-with-a-thrashing-error) for recovery steps.

138 

139Run `/context` to see what's using space. MCP tool definitions are deferred by default and loaded on demand via [tool search](/en/mcp#scale-with-mcp-tool-search), so only tool names consume context until Claude uses a specific tool. Run `/mcp` to check per-server costs.

117 140 

118#### Manage context with skills and subagents141#### Manage context with skills and subagents

119 142 


140Press `Shift+Tab` to cycle through permission modes:163Press `Shift+Tab` to cycle through permission modes:

141 164 

142* **Default**: Claude asks before file edits and shell commands165* **Default**: Claude asks before file edits and shell commands

143* **Auto-accept edits**: Claude edits files without asking, still asks for commands166* **Auto-accept edits**: Claude edits files and runs common filesystem commands like `mkdir` and `mv` without asking, still asks for other commands

144* **Plan mode**: Claude uses read-only tools only, creating a plan you can approve before execution167* **Plan mode**: Claude uses read-only tools only, creating a plan you can approve before execution

168* **Auto mode**: Claude evaluates all actions with background safety checks. Currently a research preview

145 169 

146You can also allow specific commands in `.claude/settings.json` so Claude doesn't ask each time. This is useful for trusted commands like `npm test` or `git status`. Settings can be scoped from organization-wide policies down to personal preferences. See [Permissions](/en/iam) for details.170You can also allow specific commands in `.claude/settings.json` so Claude doesn't ask each time. This is useful for trusted commands like `npm test` or `git status`. Settings can be scoped from organization-wide policies down to personal preferences. See [Permissions](/en/permissions) for details.

147 171 

148***172***

149 173 


165 189 

166Claude Code is conversational. You don't need perfect prompts. Start with what you want, then refine:190Claude Code is conversational. You don't need perfect prompts. Start with what you want, then refine:

167 191 

192```text theme={null}

193Fix the login bug

168```194```

169> Fix the login bug

170 

171[Claude investigates, tries something]

172 195 

173> That's not quite right. The issue is in the session handling.196\[Claude investigates, tries something]

174 197 

175[Claude adjusts approach]198```text theme={null}

199That's not quite right. The issue is in the session handling.

176```200```

177 201 

202\[Claude adjusts approach]

203 

178When the first attempt isn't right, you don't start over. You iterate.204When the first attempt isn't right, you don't start over. You iterate.

179 205 

180#### Interrupt and steer206#### Interrupt and steer


185 211 

186The more precise your initial prompt, the fewer corrections you'll need. Reference specific files, mention constraints, and point to example patterns.212The more precise your initial prompt, the fewer corrections you'll need. Reference specific files, mention constraints, and point to example patterns.

187 213 

188```214```text theme={null}

189> The checkout flow is broken for users with expired cards.215The checkout flow is broken for users with expired cards.

190> Check src/payments/ for the issue, especially token refresh.216Check src/payments/ for the issue, especially token refresh.

191> Write a failing test first, then fix it.217Write a failing test first, then fix it.

192```218```

193 219 

194Vague prompts like "fix the login bug" work, but you'll spend more time steering. Specific prompts like the above often succeed on the first attempt.220Vague prompts work, but you'll spend more time steering. Specific prompts like the one above often succeed on the first attempt.

195 221 

196### Give Claude something to verify against222### Give Claude something to verify against

197 223 

198Claude performs better when it can check its own work. Include test cases, paste screenshots of expected UI, or define the output you want.224Claude performs better when it can check its own work. Include test cases, paste screenshots of expected UI, or define the output you want.

199 225 

200```226```text theme={null}

201> Implement validateEmail. Test cases: 'user@example.com' → true,227Implement validateEmail. Test cases: 'user@example.com' → true,

202> 'invalid' → false, 'user@.com' → false. Run the tests after.228'invalid' → false, 'user@.com' → false. Run the tests after.

203```229```

204 230 

205For visual work, paste a screenshot of the design and ask Claude to compare its implementation against it.231For visual work, paste a screenshot of the design and ask Claude to compare its implementation against it.


208 234 

209For complex problems, separate research from coding. Use plan mode (`Shift+Tab` twice) to analyze the codebase first:235For complex problems, separate research from coding. Use plan mode (`Shift+Tab` twice) to analyze the codebase first:

210 236 

211```237```text theme={null}

212> Read src/auth/ and understand how we handle sessions.238Read src/auth/ and understand how we handle sessions.

213> Then create a plan for adding OAuth support.239Then create a plan for adding OAuth support.

214```240```

215 241 

216Review the plan, refine it through conversation, then let Claude implement. This two-phase approach produces better results than jumping straight to code.242Review the plan, refine it through conversation, then let Claude implement. This two-phase approach produces better results than jumping straight to code.


219 245 

220Think of delegating to a capable colleague. Give context and direction, then trust Claude to figure out the details:246Think of delegating to a capable colleague. Give context and direction, then trust Claude to figure out the details:

221 247 

222```248```text theme={null}

223> The checkout flow is broken for users with expired cards.249The checkout flow is broken for users with expired cards.

224> The relevant code is in src/payments/. Can you investigate and fix it?250The relevant code is in src/payments/. Can you investigate and fix it?

225```251```

226 252 

227You don't need to specify which files to read or what commands to run. Claude figures that out.253You don't need to specify which files to read or what commands to run. Claude figures that out.

iam.md +0 −239 deleted

File DeletedView Diff

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# Identity and Access Management

6 

7> Learn how to configure user authentication, authorization, and access controls for Claude Code in your organization.

8 

9## Authentication methods

10 

11Setting up Claude Code requires access to Anthropic models. For teams, you can set up Claude Code access in one of these ways:

12 

13* [Claude for Teams or Enterprise](/en/setup#for-teams-and-organizations) (recommended)

14* [Claude Console with team billing](/en/setup#for-teams-and-organizations)

15* [Amazon Bedrock](/en/amazon-bedrock)

16* [Google Vertex AI](/en/google-vertex-ai)

17* [Microsoft Foundry](/en/microsoft-foundry)

18 

19### Claude for Teams or Enterprise (recommended)

20 

21[Claude for Teams](https://claude.com/pricing#team-&-enterprise) and [Claude for Enterprise](https://anthropic.com/contact-sales) provide the best experience for organizations using Claude Code. Team members get access to both Claude Code and Claude on the web with centralized billing and team management.

22 

23* **Claude for Teams**: Self-service plan with collaboration features, admin tools, and billing management. Best for smaller teams.

24* **Claude for Enterprise**: Adds SSO, domain capture, role-based permissions, compliance API, and managed policy settings for organization-wide Claude Code configurations. Best for larger organizations with security and compliance requirements.

25 

26**To set up Claude Code access:**

27 

281. Subscribe to [Claude for Teams](https://claude.com/pricing#team-&-enterprise) or contact sales for [Claude for Enterprise](https://anthropic.com/contact-sales)

292. Invite team members from the admin dashboard

303. Team members install Claude Code and log in with their Claude.ai accounts

31 

32### Claude Console authentication

33 

34For organizations that prefer API-based billing, you can set up access through the Claude Console.

35 

36**To set up Claude Code access for your team via Claude Console:**

37 

381. Use your existing Claude Console account or create a new Claude Console account

392. You can add users through either method below:

40 * Bulk invite users from within the Console (Console -> Settings -> Members -> Invite)

41 * [Set up SSO](https://support.claude.com/en/articles/13132885-setting-up-single-sign-on-sso)

423. When inviting users, they need one of the following roles:

43 * "Claude Code" role means users can only create Claude Code API keys

44 * "Developer" role means users can create any kind of API key

454. Each invited user needs to complete these steps:

46 * Accept the Console invite

47 * [Check system requirements](/en/setup#system-requirements)

48 * [Install Claude Code](/en/setup#installation)

49 * Login with Console account credentials

50 

51### Cloud provider authentication

52 

53**To set up Claude Code access for your team via Bedrock, Vertex, or Azure:**

54 

551. Follow the [Bedrock docs](/en/amazon-bedrock), [Vertex docs](/en/google-vertex-ai), or [Microsoft Foundry docs](/en/microsoft-foundry)

562. Distribute the environment variables and instructions for generating cloud credentials to your users. Read more about how to [manage configuration here](/en/settings).

573. Users can [install Claude Code](/en/setup#installation)

58 

59## Access control and permissions

60 

61We support fine-grained permissions so that you're able to specify exactly what the agent is allowed to do (e.g. run tests, run linter) and what it is not allowed to do (e.g. update cloud infrastructure). These permission settings can be checked into version control and distributed to all developers in your organization, as well as customized by individual developers.

62 

63### Permission system

64 

65Claude Code uses a tiered permission system to balance power and safety:

66 

67| Tool Type | Example | Approval Required | "Yes, don't ask again" Behavior |

68| :---------------- | :--------------- | :---------------- | :-------------------------------------------- |

69| Read-only | File reads, Grep | No | N/A |

70| Bash Commands | Shell execution | Yes | Permanently per project directory and command |

71| File Modification | Edit/write files | Yes | Until session end |

72 

73### Configuring permissions

74 

75You can view & manage Claude Code's tool permissions with `/permissions`. This UI lists all permission rules and the settings.json file they are sourced from.

76 

77* **Allow** rules let Claude Code use the specified tool without manual approval.

78* **Ask** rules prompt for confirmation whenever Claude Code tries to use the specified tool.

79* **Deny** rules prevent Claude Code from using the specified tool.

80 

81Rules are evaluated in order: **deny → ask → allow**. The first matching rule wins, so deny rules always take precedence.

82 

83* **Additional directories** extend Claude's file access to directories beyond the initial working directory.

84* **Default mode** controls Claude's permission behavior when encountering new requests.

85 

86Permission rules use the format: `Tool` or `Tool(optional-specifier)`

87 

88A rule that is just the tool name matches any use of that tool. For example, adding `Bash` to the allow list allows Claude Code to use the Bash tool without requiring user approval. `Bash(*)` is equivalent to `Bash` and can be used interchangeably.

89 

90<Note>

91 For a quick reference on permission rule syntax including wildcards, see [Permission rule syntax](/en/settings#permission-rule-syntax) in the settings documentation.

92</Note>

93 

94#### Permission modes

95 

96Claude Code supports several permission modes that can be set as the `defaultMode` in [settings files](/en/settings#settings-files):

97 

98| Mode | Description |

99| :------------------ | :------------------------------------------------------------------------------------------------------------------------ |

100| `default` | Standard behavior - prompts for permission on first use of each tool |

101| `acceptEdits` | Automatically accepts file edit permissions for the session |

102| `plan` | Plan Mode - Claude can analyze but not modify files or execute commands |

103| `dontAsk` | Auto-denies tools unless pre-approved via `/permissions` or [`permissions.allow`](/en/settings#permission-settings) rules |

104| `bypassPermissions` | Skips all permission prompts (requires safe environment - see warning below) |

105 

106#### Working directories

107 

108By default, Claude has access to files in the directory where it was launched. You can extend this access:

109 

110* **During startup**: Use `--add-dir <path>` CLI argument

111* **During session**: Use `/add-dir` command

112* **Persistent configuration**: Add to `additionalDirectories` in [settings files](/en/settings#settings-files)

113 

114Files in additional directories follow the same permission rules as the original working directory - they become readable without prompts, and file editing permissions follow the current permission mode.

115 

116#### Tool-specific permission rules

117 

118Some tools support more fine-grained permission controls:

119 

120**Bash**

121 

122Bash permission rules support wildcard matching with `*`. Wildcards can appear at any position in the command, including at the beginning, middle, or end:

123 

124* `Bash(npm run build)` Matches the exact Bash command `npm run build`

125* `Bash(npm run test *)` Matches Bash commands starting with `npm run test`

126* `Bash(npm *)` Matches any command starting with `npm ` (e.g., `npm install`, `npm run build`)

127* `Bash(* install)` Matches any command ending with ` install` (e.g., `npm install`, `yarn install`)

128* `Bash(git * main)` Matches commands like `git checkout main`, `git merge main`

129* `Bash(* --help *)` Matches any command with `--help` followed by additional arguments

130 

131When `*` appears at the end with a space before it (like `Bash(ls *)`), it enforces a word boundary, requiring the prefix to be followed by a space or end-of-string. For example, `Bash(ls *)` matches `ls -la` but not `lsof`. In contrast, `Bash(ls*)` without a space matches both `ls -la` and `lsof` because there's no word boundary constraint. The legacy `:*` suffix syntax is equivalent to ` *` but is deprecated.

132 

133<Tip>

134 Claude Code is aware of shell operators (like `&&`) so a prefix match rule like `Bash(safe-cmd *)` won't give it permission to run the command `safe-cmd && other-cmd`

135</Tip>

136 

137<Warning>

138 Important limitations of Bash permission patterns:

139 

140 1. The space before `*` matters: `Bash(ls *)` matches `ls -la` but not `lsof`, while `Bash(ls*)` matches both

141 2. The `*` wildcard can appear at any position and matches any sequence of characters

142 3. Patterns like `Bash(curl http://github.com/ *)` can be bypassed in many ways:

143 * Options before URL: `curl -X GET http://github.com/...` won't match

144 * Different protocol: `curl https://github.com/...` won't match

145 * Redirects: `curl -L http://bit.ly/xyz` (redirects to github)

146 * Variables: `URL=http://github.com && curl $URL` won't match

147 * Extra spaces: `curl http://github.com` won't match

148 

149 For more reliable URL filtering, consider:

150 

151 * **Restrict Bash network tools**: Use deny rules to block `curl`, `wget`, and similar commands, then use the WebFetch tool with `WebFetch(domain:github.com)` permission for allowed domains

152 * **Use PreToolUse hooks**: Implement a hook that validates URLs in Bash commands and blocks disallowed domains

153 * Instructing Claude Code about your allowed curl patterns via CLAUDE.md

154 

155 Note that using WebFetch alone does not prevent network access. If Bash is allowed, Claude can still use `curl`, `wget`, or other tools to reach any URL.

156</Warning>

157 

158**Read & Edit**

159 

160`Edit` rules apply to all built-in tools that edit files. Claude will make a best-effort attempt to apply `Read` rules to all built-in tools that read files like Grep and Glob.

161 

162Read & Edit rules both follow the [gitignore](https://git-scm.com/docs/gitignore) specification with four distinct pattern types:

163 

164| Pattern | Meaning | Example | Matches |

165| ------------------ | -------------------------------------- | -------------------------------- | ---------------------------------- |

166| `//path` | **Absolute** path from filesystem root | `Read(//Users/alice/secrets/**)` | `/Users/alice/secrets/**` |

167| `~/path` | Path from **home** directory | `Read(~/Documents/*.pdf)` | `/Users/alice/Documents/*.pdf` |

168| `/path` | Path **relative to settings file** | `Edit(/src/**/*.ts)` | `<settings file path>/src/**/*.ts` |

169| `path` or `./path` | Path **relative to current directory** | `Read(*.env)` | `<cwd>/*.env` |

170 

171<Warning>

172 A pattern like `/Users/alice/file` is NOT an absolute path - it's relative to your settings file! Use `//Users/alice/file` for absolute paths.

173</Warning>

174 

175* `Edit(/docs/**)` - Edits in `<project>/docs/` (NOT `/docs/`!)

176* `Read(~/.zshrc)` - Reads your home directory's `.zshrc`

177* `Edit(//tmp/scratch.txt)` - Edits the absolute path `/tmp/scratch.txt`

178* `Read(src/**)` - Reads from `<current-directory>/src/`

179 

180<Note>

181 In gitignore patterns, `*` matches files in a single directory while `**` matches recursively across directories. To allow all file access, use just the tool name without parentheses: `Read`, `Edit`, or `Write`.

182</Note>

183 

184**WebFetch**

185 

186* `WebFetch(domain:example.com)` Matches fetch requests to example.com

187 

188**MCP**

189 

190* `mcp__puppeteer` Matches any tool provided by the `puppeteer` server (name configured in Claude Code)

191* `mcp__puppeteer__*` Wildcard syntax that also matches all tools from the `puppeteer` server

192* `mcp__puppeteer__puppeteer_navigate` Matches the `puppeteer_navigate` tool provided by the `puppeteer` server

193 

194**Task (Subagents)**

195 

196Use `Task(AgentName)` rules to control which [subagents](/en/sub-agents) Claude can use:

197 

198* `Task(Explore)` Matches the Explore subagent

199* `Task(Plan)` Matches the Plan subagent

200* `Task(Verify)` Matches the Verify subagent

201 

202Add these rules to the `deny` array in your [settings](/en/settings#permission-settings) or use the `--disallowedTools` CLI flag to disable specific agents. For example, to disable the Explore agent:

203 

204```json theme={null}

205{

206 "permissions": {

207 "deny": ["Task(Explore)"]

208 }

209}

210```

211 

212### Additional permission control with hooks

213 

214[Claude Code hooks](/en/hooks-guide) provide a way to register custom shell commands to perform permission evaluation at runtime. When Claude Code makes a tool call, PreToolUse hooks run before the permission system runs, and the hook output can determine whether to approve or deny the tool call in place of the permission system.

215 

216### Managed settings

217 

218For organizations that need centralized control over Claude Code configuration, administrators can deploy `managed-settings.json` files to [system directories](/en/settings#settings-files). These policy files follow the same format as regular settings files and cannot be overridden by user or project settings.

219 

220### Settings precedence

221 

222When multiple settings sources exist, they are applied in the following order (highest to lowest precedence):

223 

2241. Managed settings (`managed-settings.json`)

2252. Command line arguments

2263. Local project settings (`.claude/settings.local.json`)

2274. Shared project settings (`.claude/settings.json`)

2285. User settings (`~/.claude/settings.json`)

229 

230This hierarchy ensures that organizational policies are always enforced while still allowing flexibility at the project and user levels where appropriate.

231 

232## Credential management

233 

234Claude Code securely manages your authentication credentials:

235 

236* **Storage location**: On macOS, API keys, OAuth tokens, and other credentials are stored in the encrypted macOS Keychain.

237* **Supported authentication types**: Claude.ai credentials, Claude API credentials, Azure Auth, Bedrock Auth, and Vertex Auth.

238* **Custom credential scripts**: The [`apiKeyHelper`](/en/settings#available-settings) setting can be configured to run a shell script that returns an API key.

239* **Refresh intervals**: By default, `apiKeyHelper` is called after 5 minutes or on HTTP 401 response. Set `CLAUDE_CODE_API_KEY_HELPER_TTL_MS` environment variable for custom refresh intervals.

interactive-mode.md +137 −81

Details

11<Note>11<Note>

12 Keyboard shortcuts may vary by platform and terminal. Press `?` to see available shortcuts for your environment.12 Keyboard shortcuts may vary by platform and terminal. Press `?` to see available shortcuts for your environment.

13 13 

14 **macOS users**: Option/Alt key shortcuts (`Alt+B`, `Alt+F`, `Alt+Y`, `Alt+M`, `Alt+P`) require configuring Option as Meta in your terminal:14 **macOS users**: Option/Alt key shortcuts (`Alt+B`, `Alt+F`, `Alt+Y`, `Alt+M`, `Alt+P`, `Alt+T`) require configuring Option as Meta in your terminal:

15 15 

16 * **iTerm2**: Settings → Profiles → Keys → Set Left/Right Option key to "Esc+"16 * **iTerm2**: Settings → Profiles → Keys → General → set Left/Right Option key to "Esc+"

17 * **Terminal.app**: Settings → Profiles → Keyboard → Check "Use Option as Meta Key"17 * **Apple Terminal**: Settings → Profiles → Keyboard → check "Use Option as Meta Key"

18 * **VS Code**: Settings → Profiles → Keys → Set Left/Right Option key to "Esc+"18 * **VS Code**: set `"terminal.integrated.macOptionIsMeta": true` in VS Code settings

19 19 

20 See [Terminal configuration](/en/terminal-config) for details.20 See [Terminal configuration](/en/terminal-config) for details.

21</Note>21</Note>


23### General controls23### General controls

24 24 

25| Shortcut | Description | Context |25| Shortcut | Description | Context |

26| :------------------------------------------------ | :--------------------------------- | :-------------------------------------------------------------------------------------------- |26| :------------------------------------------------ | :------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

27| `Ctrl+C` | Cancel current input or generation | Standard interrupt |27| `Ctrl+C` | Cancel current input or generation | Standard interrupt |

28| `Ctrl+X Ctrl+K` | Kill all background agents. Press twice within 3 seconds to confirm | Background agent control |

28| `Ctrl+D` | Exit Claude Code session | EOF signal |29| `Ctrl+D` | Exit Claude Code session | EOF signal |

29| `Ctrl+G` | Open in default text editor | Edit your prompt or custom response in your default text editor |30| `Ctrl+G` or `Ctrl+X Ctrl+E` | Open in default text editor | Edit your prompt or custom response in your default text editor. `Ctrl+X Ctrl+E` is the readline-native binding. Turn on Show last response in external editor in `/config` to prepend Claude's previous reply as `#`-commented context above your prompt; the comment block is stripped when you save |

30| `Ctrl+L` | Clear terminal screen | Keeps conversation history |31| `Ctrl+L` | Clear prompt input and redraw screen | Clears typed text and forces a full terminal redraw. Conversation history is kept. Use this to recover if the display becomes garbled or partially blank |

31| `Ctrl+O` | Toggle verbose output | Shows detailed tool usage and execution |32| `Ctrl+O` | Toggle transcript viewer | Shows detailed tool usage and execution. Also expands MCP calls, which collapse to a single line like "Called slack 3 times" by default |

32| `Ctrl+R` | Reverse search command history | Search through previous commands interactively |33| `Ctrl+R` | Reverse search command history | Search through previous commands interactively |

33| `Ctrl+V` or `Cmd+V` (iTerm2) or `Alt+V` (Windows) | Paste image from clipboard | Pastes an image or path to an image file |34| `Ctrl+V` or `Cmd+V` (iTerm2) or `Alt+V` (Windows) | Paste image from clipboard | Inserts an `[Image #N]` chip at the cursor so you can reference it positionally in your prompt |

34| `Ctrl+B` | Background running tasks | Backgrounds bash commands and agents. Tmux users press twice |35| `Ctrl+B` | Background running tasks | Backgrounds bash commands and agents. Tmux users press twice |

36| `Ctrl+T` | Toggle task list | Show or hide the [task list](#task-list) in the terminal status area |

35| `Left/Right arrows` | Cycle through dialog tabs | Navigate between tabs in permission dialogs and menus |37| `Left/Right arrows` | Cycle through dialog tabs | Navigate between tabs in permission dialogs and menus |

36| `Up/Down arrows` | Navigate command history | Recall previous inputs |38| `Up/Down arrows` or `Ctrl+P`/`Ctrl+N` | Move cursor or navigate command history | In multiline input, first moves the cursor within the prompt. Once the cursor is already on the top or bottom edge, pressing again navigates command history |

37| `Esc` + `Esc` | Rewind the code/conversation | Restore the code and/or conversation to a previous point |39| `Esc` + `Esc` | Rewind or summarize | Restore code and/or conversation to a previous point, or summarize from a selected message |

38| `Shift+Tab` or `Alt+M` (some configurations) | Toggle permission modes | Switch between Auto-Accept Mode, Plan Mode, and normal mode |40| `Shift+Tab` or `Alt+M` (some configurations) | Cycle permission modes | Cycle through `default`, `acceptEdits`, `plan`, and any modes you have enabled, such as `auto` or `bypassPermissions`. See [permission modes](/en/permission-modes). |

39| `Option+P` (macOS) or `Alt+P` (Windows/Linux) | Switch model | Switch models without clearing your prompt |41| `Option+P` (macOS) or `Alt+P` (Windows/Linux) | Switch model | Switch models without clearing your prompt |

40| `Option+T` (macOS) or `Alt+T` (Windows/Linux) | Toggle extended thinking | Enable or disable extended thinking mode. Run `/terminal-setup` first to enable this shortcut |42| `Option+T` (macOS) or `Alt+T` (Windows/Linux) | Toggle extended thinking | Enable or disable extended thinking mode. On macOS, configure your terminal to send Option as Meta for this shortcut to work |

43| `Option+O` (macOS) or `Alt+O` (Windows/Linux) | Toggle fast mode | Enable or disable [fast mode](/en/fast-mode) |

41 44 

42### Text editing45### Text editing

43 46 

44| Shortcut | Description | Context |47| Shortcut | Description | Context |

45| :----------------------- | :--------------------------- | :------------------------------------------------------------------------------------------------------------ |48| :----------------------- | :----------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

49| `Ctrl+A` | Move cursor to start of current line | In multiline input, moves to the start of the current logical line |

50| `Ctrl+E` | Move cursor to end of current line | In multiline input, moves to the end of the current logical line |

46| `Ctrl+K` | Delete to end of line | Stores deleted text for pasting |51| `Ctrl+K` | Delete to end of line | Stores deleted text for pasting |

47| `Ctrl+U` | Delete entire line | Stores deleted text for pasting |52| `Ctrl+U` | Delete from cursor to line start | Stores deleted text for pasting. Repeat to clear across lines in multiline input. On macOS, terminal emulators including iTerm2 and Terminal.app map `Cmd+Backspace` to this shortcut |

48| `Ctrl+Y` | Paste deleted text | Paste text deleted with `Ctrl+K` or `Ctrl+U` |53| `Ctrl+W` | Delete previous word | Stores deleted text for pasting. On Windows, `Ctrl+Backspace` also deletes the previous word |

54| `Ctrl+Y` | Paste deleted text | Paste text deleted with `Ctrl+K`, `Ctrl+U`, or `Ctrl+W` |

49| `Alt+Y` (after `Ctrl+Y`) | Cycle paste history | After pasting, cycle through previously deleted text. Requires [Option as Meta](#keyboard-shortcuts) on macOS |55| `Alt+Y` (after `Ctrl+Y`) | Cycle paste history | After pasting, cycle through previously deleted text. Requires [Option as Meta](#keyboard-shortcuts) on macOS |

50| `Alt+B` | Move cursor back one word | Word navigation. Requires [Option as Meta](#keyboard-shortcuts) on macOS |56| `Alt+B` | Move cursor back one word | Word navigation. Requires [Option as Meta](#keyboard-shortcuts) on macOS |

51| `Alt+F` | Move cursor forward one word | Word navigation. Requires [Option as Meta](#keyboard-shortcuts) on macOS |57| `Alt+F` | Move cursor forward one word | Word navigation. Requires [Option as Meta](#keyboard-shortcuts) on macOS |


56| :------- | :----------------------------------------- | :----------------------------------------------------------------------------------------------------------- |62| :------- | :----------------------------------------- | :----------------------------------------------------------------------------------------------------------- |

57| `Ctrl+T` | Toggle syntax highlighting for code blocks | Only works inside the `/theme` picker menu. Controls whether code in Claude's responses uses syntax coloring |63| `Ctrl+T` | Toggle syntax highlighting for code blocks | Only works inside the `/theme` picker menu. Controls whether code in Claude's responses uses syntax coloring |

58 64 

59<Note>

60 Syntax highlighting is only available in the native build of Claude Code.

61</Note>

62 

63### Multiline input65### Multiline input

64 66 

65| Method | Shortcut | Context |67| Method | Shortcut | Context |

66| :--------------- | :------------- | :------------------------------------------------------ |68| :--------------- | :------------- | :------------------------------------------------------------------------------------------------- |

67| Quick escape | `\` + `Enter` | Works in all terminals |69| Quick escape | `\` + `Enter` | Works in all terminals |

68| macOS default | `Option+Enter` | Default on macOS |70| Option key | `Option+Enter` | After enabling [Option as Meta](/en/terminal-config#enable-option-key-shortcuts-on-macos) on macOS |

69| Shift+Enter | `Shift+Enter` | Works out of the box in iTerm2, WezTerm, Ghostty, Kitty |71| Shift+Enter | `Shift+Enter` | Native in iTerm2, WezTerm, Ghostty, Kitty, Warp, Apple Terminal |

70| Control sequence | `Ctrl+J` | Line feed character for multiline |72| Control sequence | `Ctrl+J` | Works in any terminal without configuration |

71| Paste mode | Paste directly | For code blocks, logs |73| Paste mode | Paste directly | For code blocks, logs |

72 74 

73<Tip>75<Tip>

74 Shift+Enter works without configuration in iTerm2, WezTerm, Ghostty, and Kitty. For other terminals (VS Code, Alacritty, Zed, Warp), run `/terminal-setup` to install the binding.76 Shift+Enter works without configuration in iTerm2, WezTerm, Ghostty, Kitty, Warp, and Apple Terminal. For VS Code, Cursor, Windsurf, Alacritty, and Zed, run `/terminal-setup` to install the binding.

75</Tip>77</Tip>

76 78 

77### Quick commands79### Quick commands

78 80 

79| Shortcut | Description | Notes |81| Shortcut | Description | Notes |

80| :----------- | :---------------- | :------------------------------------------------------------------- |82| :----------- | :---------------- | :------------------------------------------------------------ |

81| `/` at start | Command or skill | See [built-in commands](#built-in-commands) and [skills](/en/skills) |83| `/` at start | Command or skill | See [commands](#commands) and [skills](/en/skills) |

82| `!` at start | Bash mode | Run commands directly and add execution output to the session |84| `!` at start | Bash mode | Run commands directly and add execution output to the session |

83| `@` | File path mention | Trigger file path autocomplete |85| `@` | File path mention | Trigger file path autocomplete |

84 86 

85## Built-in commands87### Transcript viewer

86 88 

87Built-in commands are shortcuts for common actions. The table below covers commonly used commands but not all available options. Type `/` in Claude Code to see the full list, or type `/` followed by any letters to filter.89When the transcript viewer is open (toggled with `Ctrl+O`), these shortcuts are available. `Ctrl+E` can be rebound via [`transcript:toggleShowAll`](/en/keybindings).

88 90 

89To create your own commands you can invoke with `/`, see [skills](/en/skills).91| Shortcut | Description |

90 92| :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

91| Command | Purpose |93| `Ctrl+E` | Toggle show all content |

92| :------------------------ | :-------------------------------------------------------------------------------------------------------------------------- |94| `[` | Write the full conversation to your terminal's native scrollback so `Cmd+F`, tmux copy mode, and other native tools can search it. Requires [fullscreen rendering](/en/fullscreen#search-and-review-the-conversation) |

93| `/clear` | Clear conversation history |95| `v` | Write the conversation to a temporary file and open it in `$VISUAL` or `$EDITOR`. Requires [fullscreen rendering](/en/fullscreen) |

94| `/compact [instructions]` | Compact conversation with optional focus instructions |96| `q`, `Ctrl+C`, `Esc` | Exit transcript view. All three can be rebound via [`transcript:exit`](/en/keybindings) |

95| `/config` | Open the Settings interface (Config tab) |97 

96| `/context` | Visualize current context usage as a colored grid |98### Voice input

97| `/cost` | Show token usage statistics. See [cost tracking guide](/en/costs#using-the-cost-command) for subscription-specific details. |99 

98| `/doctor` | Checks the health of your Claude Code installation |100| Shortcut | Description | Notes |

99| `/exit` | Exit the REPL |101| :------------------ | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

100| `/export [filename]` | Export the current conversation to a file or clipboard |102| Hold or tap `Space` | Voice dictation | Requires [voice dictation](/en/voice-dictation) to be enabled. Hold to record, or run `/voice tap` for tap-to-toggle. [Rebindable](/en/voice-dictation#rebind-the-dictation-key) |

101| `/help` | Get usage help |103 

102| `/init` | Initialize project with `CLAUDE.md` guide |104## Commands

103| `/mcp` | Manage MCP server connections and OAuth authentication |105 

104| `/memory` | Edit `CLAUDE.md` memory files |106Type `/` in Claude Code to see all available commands, or type `/` followed by any letters to filter. The `/` menu shows everything you can invoke: built-in commands, bundled and user-authored [skills](/en/skills), and commands contributed by [plugins](/en/plugins) and [MCP servers](/en/mcp#use-mcp-prompts-as-commands). Not all built-in commands are visible to every user since some depend on your platform or plan.

105| `/model` | Select or change the AI model |107 

106| `/permissions` | View or update [permissions](/en/iam#configuring-permissions) |108See the [commands reference](/en/commands) for the full list of commands included in Claude Code.

107| `/plan` | Enter plan mode directly from the prompt |

108| `/rename <name>` | Rename the current session for easier identification |

109| `/resume [session]` | Resume a conversation by ID or name, or open the session picker |

110| `/rewind` | Rewind the conversation and/or code |

111| `/stats` | Visualize daily usage, session history, streaks, and model preferences |

112| `/status` | Open the Settings interface (Status tab) showing version, model, account, and connectivity |

113| `/statusline` | Set up Claude Code's status line UI |

114| `/copy` | Copy the last assistant response to clipboard |

115| `/tasks` | List and manage background tasks |

116| `/teleport` | Resume a remote session from claude.ai (subscribers only) |

117| `/theme` | Change the color theme |

118| `/todos` | List current TODO items |

119| `/usage` | For subscription plans only: show plan usage limits and rate limit status |

120 

121### MCP prompts

122 

123MCP servers can expose prompts that appear as commands. These use the format `/mcp__<server>__<prompt>` and are dynamically discovered from connected servers. See [MCP prompts](/en/mcp#use-mcp-prompts-as-commands) for details.

124 109 

125## Vim editor mode110## Vim editor mode

126 111 

127Enable vim-style editing with `/vim` command or configure permanently via `/config`.112Enable vim-style editing via `/config` Editor mode.

128 113 

129### Mode switching114### Mode switching

130 115 

131| Command | Action | From mode |116| Command | Action | From mode |

132| :------ | :-------------------------- | :-------- |117| :------ | :------------------------------------ | :------------- |

133| `Esc` | Enter NORMAL mode | INSERT |118| `Esc` | Enter NORMAL mode | INSERT, VISUAL |

134| `i` | Insert before cursor | NORMAL |119| `i` | Insert before cursor | NORMAL |

135| `I` | Insert at beginning of line | NORMAL |120| `I` | Insert at beginning of line | NORMAL |

136| `a` | Insert after cursor | NORMAL |121| `a` | Insert after cursor | NORMAL |

137| `A` | Insert at end of line | NORMAL |122| `A` | Insert at end of line | NORMAL |

138| `o` | Open line below | NORMAL |123| `o` | Open line below | NORMAL |

139| `O` | Open line above | NORMAL |124| `O` | Open line above | NORMAL |

125| `v` | Start character-wise visual selection | NORMAL |

126| `V` | Start line-wise visual selection | NORMAL |

140 127 

141### Navigation (NORMAL mode)128### Navigation (NORMAL mode)

142 129 


159| `,` | Repeat last f/F/t/T motion in reverse |146| `,` | Repeat last f/F/t/T motion in reverse |

160 147 

161<Note>148<Note>

162 In vim normal mode, if the cursor is at the beginning or end of input and cannot move further, the arrow keys navigate command history instead.149 In vim normal mode, if the cursor is at the beginning or end of input and cannot move further, `j`/`k` and the arrow keys navigate command history instead.

163</Note>150</Note>

164 151 

165### Editing (NORMAL mode)152### Editing (NORMAL mode)


180| `>>` | Indent line |167| `>>` | Indent line |

181| `<<` | Dedent line |168| `<<` | Dedent line |

182| `J` | Join lines |169| `J` | Join lines |

170| `u` | Undo |

183| `.` | Repeat last change |171| `.` | Repeat last change |

184 172 

185### Text objects (NORMAL mode)173### Text objects (NORMAL mode)


196| `i[`/`a[` | Inner/around brackets |184| `i[`/`a[` | Inner/around brackets |

197| `i{`/`a{` | Inner/around braces |185| `i{`/`a{` | Inner/around braces |

198 186 

187### Visual mode

188 

189Press `v` for character-wise selection or `V` for line-wise selection. Motions extend the selection, and operators act on it directly.

190 

191| Command | Action |

192| :--------------- | :--------------------------------------------------- |

193| `d`/`x` | Delete selection |

194| `y` | Yank selection |

195| `c`/`s` | Change selection |

196| `p` | Replace selection with register contents |

197| `r{char}` | Replace every selected character with `{char}` |

198| `~`/`u`/`U` | Toggle, lowercase, or uppercase selection |

199| `>`/`<` | Indent or dedent selected lines |

200| `J` | Join selected lines |

201| `o` | Swap cursor and anchor |

202| `iw`/`aw`/`i"`/… | Select a text object |

203| `v`/`V` | Toggle between character-wise and line-wise, or exit |

204 

205Block-wise visual mode with `Ctrl+V` is not supported.

206 

199## Command history207## Command history

200 208 

201Claude Code maintains command history for the current session:209Claude Code maintains command history for the current session:

202 210 

203* History is stored per working directory211* Input history is stored per working directory

204* Cleared with `/clear` command212* Input history resets when you run `/clear` to start a new session. The previous session's conversation is preserved and can be resumed.

205* Use Up/Down arrows to navigate (see keyboard shortcuts above)213* Use Up/Down arrows to navigate (see keyboard shortcuts above)

206* **Note**: History expansion (`!`) is disabled by default214* **Note**: history expansion (`!`) is disabled by default

207 215 

208### Reverse search with Ctrl+R216### Reverse search with Ctrl+R

209 217 

210Press `Ctrl+R` to interactively search through your command history:218Press `Ctrl+R` to interactively search through your command history:

211 219 

2121. **Start search**: Press `Ctrl+R` to activate reverse history search2201. **Start search**: press `Ctrl+R` to activate reverse history search

2132. **Type query**: Enter text to search for in previous commands - the search term will be highlighted in matching results2212. **Type query**: enter text to search for in previous commands. The search term is highlighted in matching results

2143. **Navigate matches**: Press `Ctrl+R` again to cycle through older matches2223. **Navigate matches**: press `Ctrl+R` again to cycle through older matches

2154. **Accept match**:2234. **Accept match**:

216 * Press `Tab` or `Esc` to accept the current match and continue editing224 * Press `Tab` or `Esc` to accept the current match and continue editing

217 * Press `Enter` to accept and execute the command immediately225 * Press `Enter` to accept and execute the command immediately


219 * Press `Ctrl+C` to cancel and restore your original input227 * Press `Ctrl+C` to cancel and restore your original input

220 * Press `Backspace` on empty search to cancel228 * Press `Backspace` on empty search to cancel

221 229 

222The search displays matching commands with the search term highlighted, making it easy to find and reuse previous inputs.230The search displays matching commands with the search term highlighted, so you can find and reuse previous inputs.

223 231 

224## Background bash commands232## Background bash commands

225 233 


236 244 

237**Key features:**245**Key features:**

238 246 

239* Output is buffered and Claude can retrieve it using the TaskOutput tool247* Output is written to a file and Claude can retrieve it using the Read tool

240* Background tasks have unique IDs for tracking and output retrieval248* Background tasks have unique IDs for tracking and output retrieval

241* Background tasks are automatically cleaned up when Claude Code exits249* Background tasks are automatically cleaned up when Claude Code exits

250* Background tasks are automatically terminated if output exceeds 5GB, with a note in stderr explaining why

242 251 

243To disable all background task functionality, set the `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` environment variable to `1`. See [Environment variables](/en/settings#environment-variables) for details.252To disable all background task functionality, set the `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` environment variable to `1`. See [Environment variables](/en/env-vars) for details.

244 253 

245**Common backgrounded commands:**254**Common backgrounded commands:**

246 255 


267* Supports the same `Ctrl+B` backgrounding for long-running commands276* Supports the same `Ctrl+B` backgrounding for long-running commands

268* Does not require Claude to interpret or approve the command277* Does not require Claude to interpret or approve the command

269* Supports history-based autocomplete: type a partial command and press **Tab** to complete from previous `!` commands in the current project278* Supports history-based autocomplete: type a partial command and press **Tab** to complete from previous `!` commands in the current project

279* Exit with `Escape`, `Backspace`, or `Ctrl+U` on an empty prompt

280* Pasting text that starts with `!` into an empty prompt enters bash mode automatically, matching typed `!` behavior

270 281 

271This is useful for quick shell operations while maintaining conversation context.282This is useful for quick shell operations while maintaining conversation context.

272 283 

284## Prompt suggestions

285 

286When you first open a session, a grayed-out example command appears in the prompt input to help you get started. Claude Code picks this from your project's git history, so it reflects files you've been working on recently.

287 

288After Claude responds, suggestions continue to appear based on your conversation history, such as a follow-up step from a multi-part request or a natural continuation of your workflow.

289 

290* Press **Tab** or **Right arrow** to accept the suggestion, or press **Enter** to accept and submit

291* Start typing to dismiss it

292 

293The suggestion runs as a background request that reuses the parent conversation's prompt cache, so the additional cost is minimal. Claude Code skips suggestion generation when the cache is cold to avoid unnecessary cost.

294 

295Suggestions are automatically skipped after the first turn of a conversation, in non-interactive mode, and in plan mode.

296 

297To disable prompt suggestions entirely, set the environment variable or toggle the setting in `/config`:

298 

299```bash theme={null}

300export CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false

301```

302 

303## Side questions with /btw

304 

305Use `/btw` to ask a quick question about your current work without adding to the conversation history. This is useful when you want a fast answer but don't want to clutter the main context or derail Claude from a long-running task.

306 

307```

308/btw what was the name of that config file again?

309```

310 

311Side questions have full visibility into the current conversation, so you can ask about code Claude has already read, decisions it made earlier, or anything else from the session. The question and answer are ephemeral: they appear in a dismissible overlay and never enter the conversation history.

312 

313* **Available while Claude is working**: you can run `/btw` even while Claude is processing a response. The side question runs independently and does not interrupt the main turn.

314* **No tool access**: side questions answer only from what is already in context. Claude cannot read files, run commands, or search when answering a side question.

315* **Single response**: there are no follow-up turns. If you need a back-and-forth, use a normal prompt instead.

316* **Low cost**: the side question reuses the parent conversation's prompt cache, so the additional cost is minimal.

317 

318Press **Space**, **Enter**, or **Escape** to dismiss the answer and return to the prompt.

319 

320`/btw` is the inverse of a [subagent](/en/sub-agents): it sees your full conversation but has no tools, while a subagent has full tools but starts with an empty context. Use `/btw` to ask about what Claude already knows from this session; use a subagent to go find out something new.

321 

273## Task list322## Task list

274 323 

275When working on complex, multi-step work, Claude creates a task list to track progress. Tasks appear in the status area of your terminal with indicators showing what's pending, in progress, or complete.324When working on complex, multi-step work, Claude creates a task list to track progress. Tasks appear in the status area of your terminal with indicators showing what's pending, in progress, or complete.

276 325 

277* Press `Ctrl+T` to toggle the task list view. The display shows up to 10 tasks at a time326* Press `Ctrl+T` to toggle the task list view. The display shows up to 5 tasks at a time

278* To see all tasks or clear them, ask Claude directly: "show me all tasks" or "clear all tasks"327* To see all tasks or clear them, ask Claude directly: "show me all tasks" or "clear all tasks"

279* Tasks persist across context compactions, helping Claude stay organized on larger projects328* Tasks persist across context compactions, helping Claude stay organized on larger projects

280* To share a task list across sessions, set `CLAUDE_CODE_TASK_LIST_ID` to use a named directory in `~/.claude/tasks/`: `CLAUDE_CODE_TASK_LIST_ID=my-project claude`329* To share a task list across sessions, set `CLAUDE_CODE_TASK_LIST_ID` to use a named directory in `~/.claude/tasks/`: `CLAUDE_CODE_TASK_LIST_ID=my-project claude`

281* To revert to the previous TODO list, set `CLAUDE_CODE_ENABLE_TASKS=false`.330 

331## Session recap

332 

333When you return to the terminal after stepping away, Claude Code shows a one-line recap of what happened in the session so far. The recap generates in the background once at least three minutes have passed since the last completed turn and the terminal is unfocused, so it's ready when you switch back. Recaps only appear once the session has at least three turns, and never twice in a row.

334 

335Run `/recap` to generate a summary on demand. To turn automatic recaps off, open `/config` and disable **Session recap**.

336 

337Session recap is on by default for every plan and provider. The recap is always skipped in non-interactive mode.

282 338 

283## PR review status339## PR review status

284 340 

jetbrains.md +6 −3

Details

51 51 

52```bash theme={null}52```bash theme={null}

53claude53claude

54> /ide54```

55 

56```text theme={null}

57/ide

55```58```

56 59 

57If you want Claude to have access to the same files as your IDE, start Claude Code from the same directory as your IDE project root.60If you want Claude to have access to the same files as your IDE, start Claude Code from the same directory as your IDE project root.


64 67 

651. Run `claude`681. Run `claude`

662. Enter the `/config` command692. Enter the `/config` command

673. Set the diff tool to `auto` for automatic IDE detection703. Set the diff tool to `auto` to show diffs in the IDE, or `terminal` to keep them in the terminal

68 71 

69### Plugin Settings72### Plugin Settings

70 73 


72 75 

73#### General Settings76#### General Settings

74 77 

75* **Claude command**: Specify a custom command to run Claude (for example, `claude`, `/usr/local/bin/claude`, or `npx @anthropic/claude`)78* **Claude command**: Specify a custom command to run Claude (for example, `claude`, `/usr/local/bin/claude`, or `npx @anthropic-ai/claude-code`)

76* **Suppress notification for Claude command not found**: Skip notifications about not finding the Claude command79* **Suppress notification for Claude command not found**: Skip notifications about not finding the Claude command

77* **Enable using Option+Enter for multi-line prompts** (macOS only): When enabled, Option+Enter inserts new lines in Claude Code prompts. Disable if experiencing issues with the Option key being captured unexpectedly (requires terminal restart)80* **Enable using Option+Enter for multi-line prompts** (macOS only): When enabled, Option+Enter inserts new lines in Claude Code prompts. Disable if experiencing issues with the Option key being captured unexpectedly (requires terminal restart)

78* **Enable automatic updates**: Automatically check for and install plugin updates (applied on restart)81* **Enable automatic updates**: Automatically check for and install plugin updates (applied on restart)

keybindings.md +107 −28

Details

6 6 

7> Customize keyboard shortcuts in Claude Code with a keybindings configuration file.7> Customize keyboard shortcuts in Claude Code with a keybindings configuration file.

8 8 

9<Note>

10 Customizable keyboard shortcuts require Claude Code v2.1.18 or later. Check your version with `claude --version`.

11</Note>

12 

9Claude Code supports customizable keyboard shortcuts. Run `/keybindings` to create or open your configuration file at `~/.claude/keybindings.json`.13Claude Code supports customizable keyboard shortcuts. Run `/keybindings` to create or open your configuration file at `~/.claude/keybindings.json`.

10 14 

11## Configuration file15## Configuration file


24 28 

25```json theme={null}29```json theme={null}

26{30{

27 "$schema": "https://platform.claude.com/docs/schemas/claude-code/keybindings.json",31 "$schema": "https://www.schemastore.org/claude-code-keybindings.json",

28 "$docs": "https://code.claude.com/docs/en/keybindings",32 "$docs": "https://code.claude.com/docs/en/keybindings",

29 "bindings": [33 "bindings": [

30 {34 {


43Each binding block specifies a **context** where the bindings apply:47Each binding block specifies a **context** where the bindings apply:

44 48 

45| Context | Description |49| Context | Description |

46| :---------------- | :----------------------------------------------- |50| :---------------- | :----------------------------------------------------------- |

47| `Global` | Applies everywhere in the app |51| `Global` | Applies everywhere in the app |

48| `Chat` | Main chat input area |52| `Chat` | Main chat input area |

49| `Autocomplete` | Autocomplete menu is open |53| `Autocomplete` | Autocomplete menu is open |

50| `Settings` | Settings menu (escape-only dismiss) |54| `Settings` | Settings menu |

51| `Confirmation` | Permission and confirmation dialogs |55| `Confirmation` | Permission and confirmation dialogs |

52| `Tabs` | Tab navigation components |56| `Tabs` | Tab navigation components |

53| `Help` | Help menu is visible |57| `Help` | Help menu is visible |


55| `HistorySearch` | History search mode (Ctrl+R) |59| `HistorySearch` | History search mode (Ctrl+R) |

56| `Task` | Background task is running |60| `Task` | Background task is running |

57| `ThemePicker` | Theme picker dialog |61| `ThemePicker` | Theme picker dialog |

58| `Attachments` | Image/attachment bar navigation |62| `Attachments` | Image attachment navigation in select dialogs |

59| `Footer` | Footer indicator navigation (tasks, teams, diff) |63| `Footer` | Footer indicator navigation (tasks, teams, diff) |

60| `MessageSelector` | Rewind dialog message selection |64| `MessageSelector` | Rewind and summarize dialog message selection |

61| `DiffDialog` | Diff viewer navigation |65| `DiffDialog` | Diff viewer navigation |

62| `ModelPicker` | Model picker effort level |66| `ModelPicker` | Model picker effort level |

63| `Select` | Generic select/list components |67| `Select` | Generic select/list components |

64| `Plugin` | Plugin dialog (browse, discover, manage) |68| `Plugin` | Plugin dialog (browse, discover, manage) |

69| `Scroll` | Conversation scrolling and text selection in fullscreen mode |

70| `Doctor` | `/doctor` diagnostics screen |

65 71 

66## Available actions72## Available actions

67 73 


72Actions available in the `Global` context:78Actions available in the `Global` context:

73 79 

74| Action | Default | Description |80| Action | Default | Description |

75| :--------------------- | :------ | :-------------------------- |81| :--------------------- | :-------- | :-------------------------- |

76| `app:interrupt` | Ctrl+C | Cancel current operation |82| `app:interrupt` | Ctrl+C | Cancel current operation |

77| `app:exit` | Ctrl+D | Exit Claude Code |83| `app:exit` | Ctrl+D | Exit Claude Code |

84| `app:redraw` | (unbound) | Force terminal redraw |

78| `app:toggleTodos` | Ctrl+T | Toggle task list visibility |85| `app:toggleTodos` | Ctrl+T | Toggle task list visibility |

79| `app:toggleTranscript` | Ctrl+O | Toggle verbose transcript |86| `app:toggleTranscript` | Ctrl+O | Toggle verbose transcript |

80 87 


93Actions available in the `Chat` context:100Actions available in the `Chat` context:

94 101 

95| Action | Default | Description |102| Action | Default | Description |

96| :-------------------- | :------------------------ | :----------------------- |103| :-------------------- | :------------------------ | :------------------------------------------------ |

97| `chat:cancel` | Escape | Cancel current input |104| `chat:cancel` | Escape | Cancel current input |

105| `chat:clearInput` | Ctrl+L | Clear prompt input and force a full screen redraw |

106| `chat:killAgents` | Ctrl+X Ctrl+K | Kill all background agents |

98| `chat:cycleMode` | Shift+Tab\* | Cycle permission modes |107| `chat:cycleMode` | Shift+Tab\* | Cycle permission modes |

99| `chat:modelPicker` | Cmd+P / Meta+P | Open model picker |108| `chat:modelPicker` | Meta+P | Open model picker |

100| `chat:thinkingToggle` | Cmd+T / Meta+T | Toggle extended thinking |109| `chat:fastMode` | Meta+O | Toggle fast mode |

110| `chat:thinkingToggle` | Meta+T | Toggle extended thinking |

101| `chat:submit` | Enter | Submit message |111| `chat:submit` | Enter | Submit message |

102| `chat:undo` | Ctrl+\_ | Undo last action |112| `chat:newline` | Ctrl+J | Insert a newline without submitting |

103| `chat:externalEditor` | Ctrl+G | Open in external editor |113| `chat:undo` | Ctrl+\_, Ctrl+Shift+- | Undo last action |

114| `chat:externalEditor` | Ctrl+G, Ctrl+X Ctrl+E | Open in external editor |

104| `chat:stash` | Ctrl+S | Stash current prompt |115| `chat:stash` | Ctrl+S | Stash current prompt |

105| `chat:imagePaste` | Ctrl+V (Alt+V on Windows) | Paste image |116| `chat:imagePaste` | Ctrl+V (Alt+V on Windows) | Paste image |

106 117 


129| `confirm:next` | Down | Next option |140| `confirm:next` | Down | Next option |

130| `confirm:nextField` | Tab | Next field |141| `confirm:nextField` | Tab | Next field |

131| `confirm:previousField` | (unbound) | Previous field |142| `confirm:previousField` | (unbound) | Previous field |

143| `confirm:toggle` | Space | Toggle selection |

132| `confirm:cycleMode` | Shift+Tab | Cycle permission modes |144| `confirm:cycleMode` | Shift+Tab | Cycle permission modes |

133| `confirm:toggleExplanation` | Ctrl+E | Toggle permission explanation |145| `confirm:toggleExplanation` | Ctrl+E | Toggle permission explanation |

134 146 


145Actions available in the `Transcript` context:157Actions available in the `Transcript` context:

146 158 

147| Action | Default | Description |159| Action | Default | Description |

148| :------------------------- | :------------- | :---------------------- |160| :------------------------- | :---------------- | :---------------------- |

149| `transcript:toggleShowAll` | Ctrl+E | Toggle show all content |161| `transcript:toggleShowAll` | Ctrl+E | Toggle show all content |

150| `transcript:exit` | Ctrl+C, Escape | Exit transcript view |162| `transcript:exit` | q, Ctrl+C, Escape | Exit transcript view |

151 163 

152### History search actions164### History search actions

153 165 


202| `attachments:next` | Right | Next attachment |214| `attachments:next` | Right | Next attachment |

203| `attachments:previous` | Left | Previous attachment |215| `attachments:previous` | Left | Previous attachment |

204| `attachments:remove` | Backspace, Delete | Remove selected attachment |216| `attachments:remove` | Backspace, Delete | Remove selected attachment |

205| `attachments:exit` | Down, Escape | Exit attachment bar |217| `attachments:exit` | Down, Escape | Exit attachment navigation |

206 218 

207### Footer actions219### Footer actions

208 220 

209Actions available in the `Footer` context:221Actions available in the `Footer` context:

210 222 

211| Action | Default | Description |223| Action | Default | Description |

212| :---------------------- | :------ | :------------------------ |224| :---------------------- | :------ | :--------------------------------------- |

213| `footer:next` | Right | Next footer item |225| `footer:next` | Right | Next footer item |

214| `footer:previous` | Left | Previous footer item |226| `footer:previous` | Left | Previous footer item |

227| `footer:up` | Up | Navigate up in footer (deselects at top) |

228| `footer:down` | Down | Navigate down in footer |

215| `footer:openSelected` | Enter | Open selected footer item |229| `footer:openSelected` | Enter | Open selected footer item |

216| `footer:clearSelection` | Escape | Clear footer selection |230| `footer:clearSelection` | Escape | Clear footer selection |

217 231 


221 235 

222| Action | Default | Description |236| Action | Default | Description |

223| :----------------------- | :---------------------------------------- | :---------------- |237| :----------------------- | :---------------------------------------- | :---------------- |

224| `messageSelector:up` | Up, K | Move up in list |238| `messageSelector:up` | Up, K, Ctrl+P | Move up in list |

225| `messageSelector:down` | Down, J | Move down in list |239| `messageSelector:down` | Down, J, Ctrl+N | Move down in list |

226| `messageSelector:top` | Ctrl+Up, Shift+Up, Meta+Up, Shift+K | Jump to top |240| `messageSelector:top` | Ctrl+Up, Shift+Up, Meta+Up, Shift+K | Jump to top |

227| `messageSelector:bottom` | Ctrl+Down, Shift+Down, Meta+Down, Shift+J | Jump to bottom |241| `messageSelector:bottom` | Ctrl+Down, Shift+Down, Meta+Down, Shift+J | Jump to bottom |

228| `messageSelector:select` | Enter | Select message |242| `messageSelector:select` | Enter | Select message |


266Actions available in the `Plugin` context:280Actions available in the `Plugin` context:

267 281 

268| Action | Default | Description |282| Action | Default | Description |

269| :--------------- | :------ | :----------------------- |283| :---------------- | :------ | :------------------------------------------------------------------------- |

270| `plugin:toggle` | Space | Toggle plugin selection |284| `plugin:toggle` | Space | Toggle plugin selection |

271| `plugin:install` | I | Install selected plugins |285| `plugin:install` | I | Install selected plugins |

286| `plugin:favorite` | F | Favorite the selected plugin so it sorts near the top of the Installed tab |

272 287 

273### Settings actions288### Settings actions

274 289 

275Actions available in the `Settings` context:290Actions available in the `Settings` context:

276 291 

277| Action | Default | Description |292| Action | Default | Description |

278| :---------------- | :------ | :---------------------------------- |293| :---------------- | :------ | :-------------------------------------------------------------------------- |

279| `settings:search` | / | Enter search mode |294| `settings:search` | / | Enter search mode |

280| `settings:retry` | R | Retry loading usage data (on error) |295| `settings:retry` | R | Retry loading usage data (on error) |

296| `settings:close` | Enter | Save changes and close the config panel. Escape discards changes and closes |

297 

298### Doctor actions

299 

300Actions available in the `Doctor` context:

301 

302| Action | Default | Description |

303| :----------- | :------ | :-------------------------------------------------------------------------------------------------- |

304| `doctor:fix` | F | Send the diagnostics report to Claude to fix the reported issues. Only active when issues are found |

305 

306### Voice actions

307 

308Actions available in the `Chat` context when [voice dictation](/en/voice-dictation) is enabled:

309 

310| Action | Default | Description |

311| :----------------- | :------ | :------------------------------------------------------- |

312| `voice:pushToTalk` | Space | Dictate a prompt. Hold or tap depending on `/voice` mode |

313 

314### Scroll actions

315 

316Actions available in the `Scroll` context when [fullscreen rendering](/en/fullscreen) is enabled:

317 

318| Action | Default | Description |

319| :-------------------------- | :------------------- | :-------------------------------------------------------------------------------------------------------- |

320| `scroll:lineUp` | (unbound) | Scroll up one line. Mouse wheel scrolling triggers this action |

321| `scroll:lineDown` | (unbound) | Scroll down one line. Mouse wheel scrolling triggers this action |

322| `scroll:pageUp` | PageUp | Scroll up half the viewport height |

323| `scroll:pageDown` | PageDown | Scroll down half the viewport height |

324| `scroll:top` | Ctrl+Home | Jump to the start of the conversation |

325| `scroll:bottom` | Ctrl+End | Jump to the latest message and re-enable auto-follow |

326| `scroll:halfPageUp` | (unbound) | Scroll up half the viewport height. Same behavior as `scroll:pageUp`, provided for vi-style rebinds |

327| `scroll:halfPageDown` | (unbound) | Scroll down half the viewport height. Same behavior as `scroll:pageDown`, provided for vi-style rebinds |

328| `scroll:fullPageUp` | (unbound) | Scroll up the full viewport height |

329| `scroll:fullPageDown` | (unbound) | Scroll down the full viewport height |

330| `selection:copy` | Ctrl+Shift+C / Cmd+C | Copy the selected text to the clipboard |

331| `selection:clear` | (unbound) | Clear the active text selection |

332| `selection:extendLeft` | Shift+Left | Extend the active selection one column left |

333| `selection:extendRight` | Shift+Right | Extend the active selection one column right |

334| `selection:extendUp` | Shift+Up | Extend the active selection one row up. Scrolls the viewport when the selection reaches the top edge |

335| `selection:extendDown` | Shift+Down | Extend the active selection one row down. Scrolls the viewport when the selection reaches the bottom edge |

336| `selection:extendLineStart` | Shift+Home | Extend the active selection to the start of the line |

337| `selection:extendLineEnd` | Shift+End | Extend the active selection to the end of the line |

281 338 

282## Keystroke syntax339## Keystroke syntax

283 340 


286Use modifier keys with the `+` separator:343Use modifier keys with the `+` separator:

287 344 

288* `ctrl` or `control` - Control key345* `ctrl` or `control` - Control key

289* `alt`, `opt`, or `option` - Alt/Option key

290* `shift` - Shift key346* `shift` - Shift key

291* `meta`, `cmd`, or `command` - Meta/Command key347* `alt`, `opt`, `option`, or `meta` - Alt key on Windows and Linux, Option key on macOS

348* `cmd`, `command`, `super`, or `win` - Command key on macOS, Windows key on Windows, Super key on Linux

349 

350The `cmd` group is only detected in terminals that report the Super modifier, such as those supporting the Kitty keyboard protocol or xterm's `modifyOtherKeys` mode. Most terminals do not send it, so use `ctrl` or `meta` for bindings you want to work everywhere.

292 351 

293For example:352For example:

294 353 

295```354```text theme={null}

296ctrl+k Single key with modifier355ctrl+k Ctrl + K

297shift+tab Shift + Tab356shift+tab Shift + Tab

298meta+p Command/Meta + P357meta+p Option + P on macOS, Alt + P elsewhere

299ctrl+shift+c Multiple modifiers358ctrl+shift+c Multiple modifiers

300```359```

301 360 


303 362 

304A standalone uppercase letter implies Shift. For example, `K` is equivalent to `shift+k`. This is useful for vim-style bindings where uppercase and lowercase keys have different meanings.363A standalone uppercase letter implies Shift. For example, `K` is equivalent to `shift+k`. This is useful for vim-style bindings where uppercase and lowercase keys have different meanings.

305 364 

306Uppercase letters with modifiers (e.g., `ctrl+K`) are treated as stylistic and do **not** imply Shift `ctrl+K` is the same as `ctrl+k`.365Uppercase letters with modifiers (e.g., `ctrl+K`) are treated as stylistic and do **not** imply Shift: `ctrl+K` is the same as `ctrl+k`.

307 366 

308### Chords367### Chords

309 368 

310Chords are sequences of keystrokes separated by spaces:369Chords are sequences of keystrokes separated by spaces:

311 370 

312```371```text theme={null}

313ctrl+k ctrl+s Press Ctrl+K, release, then Ctrl+S372ctrl+k ctrl+s Press Ctrl+K, release, then Ctrl+S

314```373```

315 374 


339}398}

340```399```

341 400 

401This also works for chord bindings. Unbinding every chord that shares a prefix frees that prefix for use as a single-key binding:

402 

403```json theme={null}

404{

405 "bindings": [

406 {

407 "context": "Chat",

408 "bindings": {

409 "ctrl+x ctrl+k": null,

410 "ctrl+x ctrl+e": null,

411 "ctrl+x": "chat:newline"

412 }

413 }

414 ]

415}

416```

417 

418If you unbind some but not all chords on a prefix, pressing the prefix still enters chord-wait mode for the remaining bindings.

419 

342## Reserved shortcuts420## Reserved shortcuts

343 421 

344These shortcuts cannot be rebound:422These shortcuts cannot be rebound:

345 423 

346| Shortcut | Reason |424| Shortcut | Reason |

347| :------- | :------------------------- |425| :------- | :--------------------------------------------- |

348| Ctrl+C | Hardcoded interrupt/cancel |426| Ctrl+C | Hardcoded interrupt/cancel |

349| Ctrl+D | Hardcoded exit |427| Ctrl+D | Hardcoded exit |

428| Ctrl+M | Identical to Enter in terminals (both send CR) |

350 429 

351## Terminal conflicts430## Terminal conflicts

352 431 


360 439 

361## Vim mode interaction440## Vim mode interaction

362 441 

363When vim mode is enabled (`/vim`), keybindings and vim mode operate independently:442When vim mode is enabled via `/config` → Editor mode, keybindings and vim mode operate independently:

364 443 

365* **Vim mode** handles input at the text input level (cursor movement, modes, motions)444* **Vim mode** handles input at the text input level (cursor movement, modes, motions)

366* **Keybindings** handle actions at the component level (toggle todos, submit, etc.)445* **Keybindings** handle actions at the component level (toggle todos, submit, etc.)

llm-gateway.md +16 −2

Details

37 Claude Code determines which features to enable based on the API format. When using the Anthropic Messages format with Bedrock or Vertex, you may need to set environment variable `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`.37 Claude Code determines which features to enable based on the API format. When using the Anthropic Messages format with Bedrock or Vertex, you may need to set environment variable `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`.

38</Note>38</Note>

39 39 

40**Request headers**

41 

42Claude Code includes the following headers on every API request:

43 

44| Header | Description |

45| :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

46| `X-Claude-Code-Session-Id` | A unique identifier for the current Claude Code session. Proxies can use this to aggregate all API requests from a single session without parsing the request body. |

47 

40## Configuration48## Configuration

41 49 

42### Model selection50### Model selection


47 55 

48## LiteLLM configuration56## LiteLLM configuration

49 57 

50<Note>58<Warning>

59 LiteLLM PyPI versions 1.82.7 and 1.82.8 were compromised with credential-stealing malware. Do not install these versions. If you have already installed them:

60 

61 * Remove the package

62 * Rotate all credentials on affected systems

63 * Follow the remediation steps in [BerriAI/litellm#24518](https://github.com/BerriAI/litellm/issues/24518)

64 

51 LiteLLM is a third-party proxy service. Anthropic doesn't endorse, maintain, or audit LiteLLM's security or functionality. This guide is provided for informational purposes and may become outdated. Use at your own discretion.65 LiteLLM is a third-party proxy service. Anthropic doesn't endorse, maintain, or audit LiteLLM's security or functionality. This guide is provided for informational purposes and may become outdated. Use at your own discretion.

52</Note>66</Warning>

53 67 

54### Prerequisites68### Prerequisites

55 69 

mcp.md +388 −93

Details

9 9 

10Claude Code can connect to hundreds of external tools and data sources through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction), an open source standard for AI-tool integrations. MCP servers give Claude Code access to your tools, databases, and APIs.10Claude Code can connect to hundreds of external tools and data sources through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction), an open source standard for AI-tool integrations. MCP servers give Claude Code access to your tools, databases, and APIs.

11 11 

12Connect a server when you find yourself copying data into chat from another tool, like an issue tracker or a monitoring dashboard. Once connected, Claude can read and act on that system directly instead of working from what you paste.

13 

12## What you can do with MCP14## What you can do with MCP

13 15 

14With MCP servers connected, you can ask Claude Code to:16With MCP servers connected, you can ask Claude Code to:


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

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

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

23* **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.

21 24 

22## Popular MCP servers25## Popular MCP servers

23 26 


123 126 

124Claude 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.127Claude 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.

125 128 

129### Automatic reconnection

130 

131If an HTTP or SSE server disconnects mid-session, Claude Code automatically reconnects with exponential backoff: up to five attempts, starting at a one-second delay and doubling each time. The server appears as pending in `/mcp` while reconnection is in progress. After five failed attempts the server is marked as failed and you can retry manually from `/mcp`. Stdio servers are local processes and are not reconnected automatically.

132 

133### Push messages with channels

134 

135An 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.

136 

126<Tip>137<Tip>

127 Tips:138 Tips:

128 139 


136 * Use `/mcp` to authenticate with remote servers that require OAuth 2.0 authentication147 * Use `/mcp` to authenticate with remote servers that require OAuth 2.0 authentication

137</Tip>148</Tip>

138 149 

139<Warning>

140 **Windows Users**: On native Windows (not WSL), local MCP servers that use `npx` require the `cmd /c` wrapper to ensure proper execution.

141 

142 ```bash theme={null}

143 # This creates command="cmd" which Windows can execute

144 claude mcp add --transport stdio my-server -- cmd /c npx -y @some/package

145 ```

146 

147 Without the `cmd /c` wrapper, you'll encounter "Connection closed" errors because Windows cannot directly execute `npx`. (See the note above for an explanation of the `--` parameter.)

148</Warning>

149 

150### Plugin-provided MCP servers150### Plugin-provided MCP servers

151 151 

152[Plugins](/en/plugins) can bundle MCP servers, automatically providing tools and integrations when the plugin is enabled. Plugin MCP servers work identically to user-configured servers.152[Plugins](/en/plugins) can bundle MCP servers, automatically providing tools and integrations when the plugin is enabled. Plugin MCP servers work identically to user-configured servers.


164 164 

165```json theme={null}165```json theme={null}

166{166{

167 "mcpServers": {

167 "database-tools": {168 "database-tools": {

168 "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",169 "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",

169 "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],170 "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],


171 "DB_URL": "${DB_URL}"172 "DB_URL": "${DB_URL}"

172 }173 }

173 }174 }

175 }

174}176}

175```177```

176 178 


190 192 

191**Plugin MCP features**:193**Plugin MCP features**:

192 194 

193* **Automatic lifecycle**: Servers start when plugin enables, but you must restart Claude Code to apply MCP server changes (enabling or disabling)195* **Automatic lifecycle**: At session startup, servers for enabled plugins connect automatically. If you enable or disable a plugin during a session, run `/reload-plugins` to connect or disconnect its MCP servers

194* **Environment variables**: Use `${CLAUDE_PLUGIN_ROOT}` for plugin-relative paths196* **Environment variables**: use `${CLAUDE_PLUGIN_ROOT}` for bundled plugin files and `${CLAUDE_PLUGIN_DATA}` for [persistent state](/en/plugins-reference#persistent-data-directory) that survives plugin updates

195* **User environment access**: Access to same environment variables as manually configured servers197* **User environment access**: Access to same environment variables as manually configured servers

196* **Multiple transport types**: Support stdio, SSE, and HTTP transports (transport support may vary by server)198* **Multiple transport types**: Support stdio, SSE, and HTTP transports (transport support may vary by server)

197 199 


214 216 

215## MCP installation scopes217## MCP installation scopes

216 218 

217MCP servers can be configured at three different scope levels, each serving distinct purposes for managing server accessibility and sharing. Understanding these scopes helps you determine the best way to configure servers for your specific needs.219MCP servers can be configured at three scopes. The scope you choose controls which projects the server loads in and whether the configuration is shared with your team.

220 

221| Scope | Loads in | Shared with team | Stored in |

222| ------------------------- | -------------------- | ------------------------ | --------------------------- |

223| [Local](#local-scope) | Current project only | No | `~/.claude.json` |

224| [Project](#project-scope) | Current project only | Yes, via version control | `.mcp.json` in project root |

225| [User](#user-scope) | All your projects | No | `~/.claude.json` |

218 226 

219### Local scope227### Local scope

220 228 

221Local-scoped servers represent the default configuration level and are stored in `~/.claude.json` under your project's path. These servers remain private to you and are only accessible when working within the current project directory. This scope is ideal for personal development servers, experimental configurations, or servers containing sensitive credentials that shouldn't be shared.229Local scope is the default. A local-scoped server loads only in the project where you added it and stays private to you. Claude Code stores it in `~/.claude.json` under that project's path, so the same server won't appear in your other projects. Use local scope for personal development servers, experimental configurations, or servers with credentials you don't want in version control.

222 230 

223<Note>231<Note>

224 The term "local scope" for MCP servers differs from general local settings. MCP local-scoped servers are stored in `~/.claude.json` (your home directory), while general local settings use `.claude/settings.local.json` (in the project directory). See [Settings](/en/settings#settings-files) for details on settings file locations.232 The term "local scope" for MCP servers differs from general local settings. MCP local-scoped servers are stored in `~/.claude.json` (your home directory), while general local settings use `.claude/settings.local.json` (in the project directory). See [Settings](/en/settings#settings-files) for details on settings file locations.


232claude mcp add --transport http stripe --scope local https://mcp.stripe.com240claude mcp add --transport http stripe --scope local https://mcp.stripe.com

233```241```

234 242 

243The command writes the server into the entry for your current project inside `~/.claude.json`. The example below shows the result when you run it from `/path/to/your/project`:

244 

245```json theme={null}

246{

247 "projects": {

248 "/path/to/your/project": {

249 "mcpServers": {

250 "stripe": {

251 "type": "http",

252 "url": "https://mcp.stripe.com"

253 }

254 }

255 }

256 }

257}

258```

259 

235### Project scope260### Project scope

236 261 

237Project-scoped servers enable team collaboration by storing configurations in a `.mcp.json` file at your project's root directory. This file is designed to be checked into version control, ensuring all team members have access to the same MCP tools and services. When you add a project-scoped server, Claude Code automatically creates or updates this file with the appropriate configuration structure.262Project-scoped servers enable team collaboration by storing configurations in a `.mcp.json` file at your project's root directory. This file is designed to be checked into version control, ensuring all team members have access to the same MCP tools and services. When you add a project-scoped server, Claude Code automatically creates or updates this file with the appropriate configuration structure.


266claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic291claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic

267```292```

268 293 

269### Choosing the right scope294### Scope hierarchy and precedence

270 295 

271Select your scope based on:296When the same server is defined in more than one place, Claude Code connects to it once, using the definition from the highest-precedence source:

272 297 

273* **Local scope**: Personal servers, experimental configurations, or sensitive credentials specific to one project2981. Local scope

274* **Project scope**: Team-shared servers, project-specific tools, or services required for collaboration2992. Project scope

275* **User scope**: Personal utilities needed across multiple projects, development tools, or frequently used services3003. User scope

3014. [Plugin-provided servers](/en/plugins)

3025. [claude.ai connectors](#use-mcp-servers-from-claude-ai)

276 303 

277<Note>304The three scopes match duplicates by name. Plugins and connectors match by endpoint, so one that points at the same URL or command as a server above is treated as a duplicate.

278 **Where are MCP servers stored?**

279 

280 * **User and local scope**: `~/.claude.json` (in the `mcpServers` field or under project paths)

281 * **Project scope**: `.mcp.json` in your project root (checked into source control)

282 * **Managed**: `managed-mcp.json` in system directories (see [Managed MCP configuration](#managed-mcp-configuration))

283</Note>

284 

285### Scope hierarchy and precedence

286 

287MCP server configurations follow a clear precedence hierarchy. When servers with the same name exist at multiple scopes, the system resolves conflicts by prioritizing local-scoped servers first, followed by project-scoped servers, and finally user-scoped servers. This design ensures that personal configurations can override shared ones when needed.

288 305 

289### Environment variable expansion in `.mcp.json`306### Environment variable expansion in `.mcp.json`

290 307 


326 343 

327{/* ### Example: Automate browser testing with Playwright344{/* ### Example: Automate browser testing with Playwright

328 345 

329 ```bash346```bash

330 # 1. Add the Playwright MCP server347claude mcp add --transport stdio playwright -- npx -y @playwright/mcp@latest

331 claude mcp add --transport stdio playwright -- npx -y @playwright/mcp@latest348```

349 

350Then write and run browser tests:

332 351 

333 # 2. Write and run browser tests352```text

334 > "Test if the login flow works with test@example.com"353Test if the login flow works with test@example.com

335 > "Take a screenshot of the checkout page on mobile"354```

336 > "Verify that the search feature returns results"355```text

337 ``` */}356Take a screenshot of the checkout page on mobile

357```

358```text

359Verify that the search feature returns results

360``` */}

338 361 

339### Example: Monitor errors with Sentry362### Example: Monitor errors with Sentry

340 363 

341```bash theme={null}364```bash theme={null}

342# 1. Add the Sentry MCP server

343claude mcp add --transport http sentry https://mcp.sentry.dev/mcp365claude mcp add --transport http sentry https://mcp.sentry.dev/mcp

366```

367 

368Authenticate with your Sentry account:

369 

370```text theme={null}

371/mcp

372```

373 

374Then debug production issues:

344 375 

345# 2. Use /mcp to authenticate with your Sentry account376```text theme={null}

346> /mcp377What are the most common errors in the last 24 hours?

378```

379 

380```text theme={null}

381Show me the stack trace for error ID abc123

382```

347 383 

348# 3. Debug production issues384```text theme={null}

349> "What are the most common errors in the last 24 hours?"385Which deployment introduced these new errors?

350> "Show me the stack trace for error ID abc123"

351> "Which deployment introduced these new errors?"

352```386```

353 387 

354### Example: Connect to GitHub for code reviews388### Example: Connect to GitHub for code reviews

355 389 

390GitHub's remote MCP server authenticates with a GitHub personal access token passed as a header. To get one, open your [GitHub token settings](https://github.com/settings/personal-access-tokens), generate a new fine-grained token with access to the repositories you want Claude to work with, then add the server:

391 

356```bash theme={null}392```bash theme={null}

357# 1. Add the GitHub MCP server393claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \

358claude mcp add --transport http github https://api.githubcopilot.com/mcp/394 --header "Authorization: Bearer YOUR_GITHUB_PAT"

395```

359 396 

360# 2. In Claude Code, authenticate if needed397Then work with GitHub:

361> /mcp

362# Select "Authenticate" for GitHub

363 398 

364# 3. Now you can ask Claude to work with GitHub399```text theme={null}

365> "Review PR #456 and suggest improvements"400Review PR #456 and suggest improvements

366> "Create a new issue for the bug we just found"401```

367> "Show me all open PRs assigned to me"402 

403```text theme={null}

404Create a new issue for the bug we just found

405```

406 

407```text theme={null}

408Show me all open PRs assigned to me

368```409```

369 410 

370### Example: Query your PostgreSQL database411### Example: Query your PostgreSQL database

371 412 

372```bash theme={null}413```bash theme={null}

373# 1. Add the database server with your connection string

374claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \414claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \

375 --dsn "postgresql://readonly:pass@prod.db.com:5432/analytics"415 --dsn "postgresql://readonly:pass@prod.db.com:5432/analytics"

416```

417 

418Then query your database naturally:

419 

420```text theme={null}

421What's our total revenue this month?

422```

376 423 

377# 2. Query your database naturally424```text theme={null}

378> "What's our total revenue this month?"425Show me the schema for the orders table

379> "Show me the schema for the orders table"426```

380> "Find customers who haven't made a purchase in 90 days"427 

428```text theme={null}

429Find customers who haven't made a purchase in 90 days

381```430```

382 431 

383## Authenticate with remote MCP servers432## Authenticate with remote MCP servers


396 <Step title="Use the /mcp command within Claude Code">445 <Step title="Use the /mcp command within Claude Code">

397 In Claude code, use the command:446 In Claude code, use the command:

398 447 

399 ```448 ```text theme={null}

400 > /mcp449 /mcp

401 ```450 ```

402 451 

403 Then follow the steps in your browser to login.452 Then follow the steps in your browser to login.


409 458 

410 * Authentication tokens are stored securely and refreshed automatically459 * Authentication tokens are stored securely and refreshed automatically

411 * Use "Clear authentication" in the `/mcp` menu to revoke access460 * Use "Clear authentication" in the `/mcp` menu to revoke access

412 * If your browser doesn't open automatically, copy the provided URL461 * If your browser doesn't open automatically, copy the provided URL and open it manually

462 * If the browser redirect fails with a connection error after authenticating, paste the full callback URL from your browser's address bar into the URL prompt that appears in Claude Code

413 * OAuth authentication works with HTTP servers463 * OAuth authentication works with HTTP servers

414</Tip>464</Tip>

415 465 

466### Use a fixed OAuth callback port

467 

468Some MCP servers require a specific redirect URI registered in advance. By default, Claude Code picks a random available port for the OAuth callback. Use `--callback-port` to fix the port so it matches a pre-registered redirect URI of the form `http://localhost:PORT/callback`.

469 

470You can use `--callback-port` on its own (with dynamic client registration) or together with `--client-id` (with pre-configured credentials).

471 

472```bash theme={null}

473# Fixed callback port with dynamic client registration

474claude mcp add --transport http \

475 --callback-port 8080 \

476 my-server https://mcp.example.com/mcp

477```

478 

479### Use pre-configured OAuth credentials

480 

481Some MCP servers don't support automatic OAuth setup via Dynamic Client Registration. If you see an error like "Incompatible auth server: does not support dynamic client registration," the server requires pre-configured credentials. Claude Code also supports servers that use a Client ID Metadata Document (CIMD) instead of Dynamic Client Registration, and discovers these automatically. If automatic discovery fails, register an OAuth app through the server's developer portal first, then provide the credentials when adding the server.

482 

483<Steps>

484 <Step title="Register an OAuth app with the server">

485 Create an app through the server's developer portal and note your client ID and client secret.

486 

487 Many servers also require a redirect URI. If so, choose a port and register a redirect URI in the format `http://localhost:PORT/callback`. Use that same port with `--callback-port` in the next step.

488 </Step>

489 

490 <Step title="Add the server with your credentials">

491 Choose one of the following methods. The port used for `--callback-port` can be any available port. It just needs to match the redirect URI you registered in the previous step.

492 

493 <Tabs>

494 <Tab title="claude mcp add">

495 Use `--client-id` to pass your app's client ID. The `--client-secret` flag prompts for the secret with masked input:

496 

497 ```bash theme={null}

498 claude mcp add --transport http \

499 --client-id your-client-id --client-secret --callback-port 8080 \

500 my-server https://mcp.example.com/mcp

501 ```

502 </Tab>

503 

504 <Tab title="claude mcp add-json">

505 Include the `oauth` object in the JSON config and pass `--client-secret` as a separate flag:

506 

507 ```bash theme={null}

508 claude mcp add-json my-server \

509 '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' \

510 --client-secret

511 ```

512 </Tab>

513 

514 <Tab title="claude mcp add-json (callback port only)">

515 Use `--callback-port` without a client ID to fix the port while using dynamic client registration:

516 

517 ```bash theme={null}

518 claude mcp add-json my-server \

519 '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"callbackPort":8080}}'

520 ```

521 </Tab>

522 

523 <Tab title="CI / env var">

524 Set the secret via environment variable to skip the interactive prompt:

525 

526 ```bash theme={null}

527 MCP_CLIENT_SECRET=your-secret claude mcp add --transport http \

528 --client-id your-client-id --client-secret --callback-port 8080 \

529 my-server https://mcp.example.com/mcp

530 ```

531 </Tab>

532 </Tabs>

533 </Step>

534 

535 <Step title="Authenticate in Claude Code">

536 Run `/mcp` in Claude Code and follow the browser login flow.

537 </Step>

538</Steps>

539 

540<Tip>

541 Tips:

542 

543 * The client secret is stored securely in your system keychain (macOS) or a credentials file, not in your config

544 * If the server uses a public OAuth client with no secret, use only `--client-id` without `--client-secret`

545 * `--callback-port` can be used with or without `--client-id`

546 * These flags only apply to HTTP and SSE transports. They have no effect on stdio servers

547 * Use `claude mcp get <name>` to verify that OAuth credentials are configured for a server

548</Tip>

549 

550### Override OAuth metadata discovery

551 

552Point Claude Code at a specific OAuth authorization server metadata URL to bypass the default discovery chain. Set `authServerMetadataUrl` when the MCP server's standard endpoints error, or when you want to route discovery through an internal proxy. By default, Claude Code first checks RFC 9728 Protected Resource Metadata at `/.well-known/oauth-protected-resource`, then falls back to RFC 8414 authorization server metadata at `/.well-known/oauth-authorization-server`.

553 

554Set `authServerMetadataUrl` in the `oauth` object of your server's config in `.mcp.json`:

555 

556```json theme={null}

557{

558 "mcpServers": {

559 "my-server": {

560 "type": "http",

561 "url": "https://mcp.example.com/mcp",

562 "oauth": {

563 "authServerMetadataUrl": "https://auth.example.com/.well-known/openid-configuration"

564 }

565 }

566 }

567}

568```

569 

570The URL must use `https://`. `authServerMetadataUrl` requires Claude Code v2.1.64 or later. The metadata URL's `scopes_supported` overrides the scopes the upstream server advertises.

571 

572### Restrict OAuth scopes

573 

574Set `oauth.scopes` to pin the scopes Claude Code requests during the authorization flow. This is the supported way to restrict an MCP server to a security-team-approved subset when the upstream authorization server advertises more scopes than you want to grant. The value is a single space-separated string, matching the `scope` parameter format in RFC 6749 §3.3.

575 

576```json theme={null}

577{

578 "mcpServers": {

579 "slack": {

580 "type": "http",

581 "url": "https://mcp.slack.com/mcp",

582 "oauth": {

583 "scopes": "channels:read chat:write search:read"

584 }

585 }

586 }

587}

588```

589 

590`oauth.scopes` takes precedence over both `authServerMetadataUrl` and the scopes the server discovers at `/.well-known`. Leave it unset to let the MCP server determine the requested scope set.

591 

592If the authorization server advertises `offline_access` in `scopes_supported`, Claude Code appends it to the pinned scopes so the access token can be refreshed without a new browser sign-in.

593 

594If the server later returns a 403 `insufficient_scope` for a tool call, Claude Code re-authenticates with the same pinned scopes. Widen `oauth.scopes` when a tool you need requires a scope outside the pin.

595 

596### Use dynamic headers for custom authentication

597 

598If your MCP server uses an authentication scheme other than OAuth (such as Kerberos, short-lived tokens, or an internal SSO), use `headersHelper` to generate request headers at connection time. Claude Code runs the command and merges its output into the connection headers.

599 

600```json theme={null}

601{

602 "mcpServers": {

603 "internal-api": {

604 "type": "http",

605 "url": "https://mcp.internal.example.com",

606 "headersHelper": "/opt/bin/get-mcp-auth-headers.sh"

607 }

608 }

609}

610```

611 

612The command can also be inline:

613 

614```json theme={null}

615{

616 "mcpServers": {

617 "internal-api": {

618 "type": "http",

619 "url": "https://mcp.internal.example.com",

620 "headersHelper": "echo '{\"Authorization\": \"Bearer '\"$(get-token)\"'\"}'"

621 }

622 }

623}

624```

625 

626**Requirements:**

627 

628* The command must write a JSON object of string key-value pairs to stdout

629* The command runs in a shell with a 10-second timeout

630* Dynamic headers override any static `headers` with the same name

631 

632The helper runs fresh on each connection (at session start and on reconnect). There is no caching, so your script is responsible for any token reuse.

633 

634Claude Code sets these environment variables when executing the helper:

635 

636| Variable | Value |

637| :---------------------------- | :------------------------- |

638| `CLAUDE_CODE_MCP_SERVER_NAME` | the name of the MCP server |

639| `CLAUDE_CODE_MCP_SERVER_URL` | the URL of the MCP server |

640 

641Use these to write a single helper script that serves multiple MCP servers.

642 

643<Note>

644 `headersHelper` executes arbitrary shell commands. When defined at project or local scope, it only runs after you accept the workspace trust dialog.

645</Note>

646 

416## Add MCP servers from JSON configuration647## Add MCP servers from JSON configuration

417 648 

418If you have a JSON configuration for an MCP server, you can add it directly:649If you have a JSON configuration for an MCP server, you can add it directly:


428 659 

429 # Example: Adding a stdio server with JSON configuration660 # Example: Adding a stdio server with JSON configuration

430 claude mcp add-json local-weather '{"type":"stdio","command":"/path/to/weather-cli","args":["--api-key","abc123"],"env":{"CACHE_DIR":"/tmp"}}'661 claude mcp add-json local-weather '{"type":"stdio","command":"/path/to/weather-cli","args":["--api-key","abc123"],"env":{"CACHE_DIR":"/tmp"}}'

662 

663 # Example: Adding an HTTP server with pre-configured OAuth credentials

664 claude mcp add-json my-server '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' --client-secret

431 ```665 ```

432 </Step>666 </Step>

433 667 


479 * If servers with the same names already exist, they will get a numerical suffix (for example, `server_1`)713 * If servers with the same names already exist, they will get a numerical suffix (for example, `server_1`)

480</Tip>714</Tip>

481 715 

716## Use MCP servers from Claude.ai

717 

718If you've logged into Claude Code with a [Claude.ai](https://claude.ai) account, MCP servers you've added in Claude.ai are automatically available in Claude Code:

719 

720<Steps>

721 <Step title="Configure MCP servers in Claude.ai">

722 Add servers at [claude.ai/customize/connectors](https://claude.ai/customize/connectors). On Team and Enterprise plans, only admins can add servers.

723 </Step>

724 

725 <Step title="Authenticate the MCP server">

726 Complete any required authentication steps in Claude.ai.

727 </Step>

728 

729 <Step title="View and manage servers in Claude Code">

730 In Claude Code, use the command:

731 

732 ```text theme={null}

733 /mcp

734 ```

735 

736 Claude.ai servers appear in the list with indicators showing they come from Claude.ai.

737 </Step>

738</Steps>

739 

740To disable claude.ai MCP servers in Claude Code, set the `ENABLE_CLAUDEAI_MCP_SERVERS` environment variable to `false`:

741 

742```bash theme={null}

743ENABLE_CLAUDEAI_MCP_SERVERS=false claude

744```

745 

482## Use Claude Code as an MCP server746## Use Claude Code as an MCP server

483 747 

484You can use Claude Code itself as an MCP server that other applications can connect to:748You can use Claude Code itself as an MCP server that other applications can connect to:


543When MCP tools produce large outputs, Claude Code helps manage the token usage to prevent overwhelming your conversation context:807When MCP tools produce large outputs, Claude Code helps manage the token usage to prevent overwhelming your conversation context:

544 808 

545* **Output warning threshold**: Claude Code displays a warning when any MCP tool output exceeds 10,000 tokens809* **Output warning threshold**: Claude Code displays a warning when any MCP tool output exceeds 10,000 tokens

546* **Configurable limit**: You can adjust the maximum allowed MCP output tokens using the `MAX_MCP_OUTPUT_TOKENS` environment variable810* **Configurable limit**: you can adjust the maximum allowed MCP output tokens using the `MAX_MCP_OUTPUT_TOKENS` environment variable

547* **Default limit**: The default maximum is 25,000 tokens811* **Default limit**: the default maximum is 25,000 tokens

812* **Scope**: the environment variable applies to tools that don't declare their own limit. Tools that set [`anthropic/maxResultSizeChars`](#raise-the-limit-for-a-specific-tool) use that value instead for text content, regardless of what `MAX_MCP_OUTPUT_TOKENS` is set to. Tools that return image data are still subject to `MAX_MCP_OUTPUT_TOKENS`

548 813 

549To increase the limit for tools that produce large outputs:814To increase the limit for tools that produce large outputs:

550 815 

551```bash theme={null}816```bash theme={null}

552# Set a higher limit for MCP tool outputs

553export MAX_MCP_OUTPUT_TOKENS=50000817export MAX_MCP_OUTPUT_TOKENS=50000

554claude818claude

555```819```


560* Generate detailed reports or documentation824* Generate detailed reports or documentation

561* Process extensive log files or debugging information825* Process extensive log files or debugging information

562 826 

827### Raise the limit for a specific tool

828 

829If you're building an MCP server, you can allow individual tools to return results larger than the default persist-to-disk threshold by setting `_meta["anthropic/maxResultSizeChars"]` in the tool's `tools/list` response entry. Claude Code raises that tool's threshold to the annotated value, up to a hard ceiling of 500,000 characters.

830 

831This is useful for tools that return inherently large but necessary outputs, such as database schemas or full file trees. Without the annotation, results that exceed the default threshold are persisted to disk and replaced with a file reference in the conversation.

832 

833```json theme={null}

834{

835 "name": "get_schema",

836 "description": "Returns the full database schema",

837 "_meta": {

838 "anthropic/maxResultSizeChars": 200000

839 }

840}

841```

842 

843The annotation applies independently of `MAX_MCP_OUTPUT_TOKENS` for text content, so users don't need to raise the environment variable for tools that declare it. Tools that return image data are still subject to the token limit.

844 

563<Warning>845<Warning>

564 If you frequently encounter output warnings with specific MCP servers, consider increasing the limit or configuring the server to paginate or filter its responses.846 If you frequently encounter output warnings with specific MCP servers you don't control, consider increasing the `MAX_MCP_OUTPUT_TOKENS` limit. You can also ask the server author to add the `anthropic/maxResultSizeChars` annotation or to paginate their responses. The annotation has no effect on tools that return image content; for those, raising `MAX_MCP_OUTPUT_TOKENS` is the only option.

565</Warning>847</Warning>

566 848 

849## Respond to MCP elicitation requests

850 

851MCP servers can request structured input from you mid-task using elicitation. When a server needs information it can't get on its own, Claude Code displays an interactive dialog and passes your response back to the server. No configuration is required on your side: elicitation dialogs appear automatically when a server requests them.

852 

853Servers can request input in two ways:

854 

855* **Form mode**: Claude Code shows a dialog with form fields defined by the server (for example, a username and password prompt). Fill in the fields and submit.

856* **URL mode**: Claude Code opens a browser URL for authentication or approval. Complete the flow in the browser, then confirm in the CLI.

857 

858To auto-respond to elicitation requests without showing a dialog, use the [`Elicitation` hook](/en/hooks#elicitation).

859 

860If you're building an MCP server that uses elicitation, see the [MCP elicitation specification](https://modelcontextprotocol.io/docs/learn/client-concepts#elicitation) for protocol details and schema examples.

861 

567## Use MCP resources862## Use MCP resources

568 863 

569MCP servers can expose resources that you can reference using @ mentions, similar to how you reference files.864MCP servers can expose resources that you can reference using @ mentions, similar to how you reference files.


578 <Step title="Reference a specific resource">873 <Step title="Reference a specific resource">

579 Use the format `@server:protocol://resource/path` to reference a resource:874 Use the format `@server:protocol://resource/path` to reference a resource:

580 875 

581 ```876 ```text theme={null}

582 > Can you analyze @github:issue://123 and suggest a fix?877 Can you analyze @github:issue://123 and suggest a fix?

583 ```878 ```

584 879 

585 ```880 ```text theme={null}

586 > Please review the API documentation at @docs:file://api/authentication881 Please review the API documentation at @docs:file://api/authentication

587 ```882 ```

588 </Step>883 </Step>

589 884 

590 <Step title="Multiple resource references">885 <Step title="Multiple resource references">

591 You can reference multiple resources in a single prompt:886 You can reference multiple resources in a single prompt:

592 887 

593 ```888 ```text theme={null}

594 > Compare @postgres:schema://users with @docs:file://database/user-model889 Compare @postgres:schema://users with @docs:file://database/user-model

595 ```890 ```

596 </Step>891 </Step>

597</Steps>892</Steps>


607 902 

608## Scale with MCP Tool Search903## Scale with MCP Tool Search

609 904 

610When you have many MCP servers configured, tool definitions can consume a significant portion of your context window. MCP Tool Search solves this by dynamically loading tools on-demand instead of preloading all of them.905Tool search keeps MCP context usage low by deferring tool definitions until Claude needs them. Only tool names load at session start, so adding more MCP servers has minimal impact on your context window.

611 906 

612### How it works907### How it works

613 908 

614Claude Code automatically enables Tool Search when your MCP tool descriptions would consume more than 10% of the context window. You can [adjust this threshold](#configure-tool-search) or disable tool search entirely. When triggered:909Tool search is enabled by default. MCP tools are deferred rather than loaded into context upfront, and Claude uses a search tool to discover relevant ones when a task needs them. Only the tools Claude actually uses enter context. From your perspective, MCP tools work exactly as before.

615 910 

6161. MCP tools are deferred rather than loaded into context upfront911If you prefer threshold-based loading, set `ENABLE_TOOL_SEARCH=auto` to load schemas upfront when they fit within 10% of the context window and defer only the overflow. See [Configure tool search](#configure-tool-search) for all options.

6172. Claude uses a search tool to discover relevant MCP tools when needed

6183. Only the tools Claude actually needs are loaded into context

6194. MCP tools continue to work exactly as before from your perspective

620 912 

621### For MCP server authors913### For MCP server authors

622 914 


628* When Claude should search for your tools920* When Claude should search for your tools

629* Key capabilities your server provides921* Key capabilities your server provides

630 922 

923Claude Code truncates tool descriptions and server instructions at 2KB each. Keep them concise to avoid truncation, and put critical details near the start.

924 

631### Configure tool search925### Configure tool search

632 926 

633Tool search runs in auto mode by default, meaning it activates only when your MCP tool definitions exceed the context threshold. If you have few tools, they load normally without tool search. This feature requires models that support `tool_reference` blocks: Sonnet 4 and later, or Opus 4 and later. Haiku models do not support tool search.927Tool search is enabled by default: MCP tools are deferred and discovered on demand. It is disabled by default on Vertex AI, which does not accept the tool search beta header, and when `ANTHROPIC_BASE_URL` points to a non-first-party host, since most proxies do not forward `tool_reference` blocks. Set `ENABLE_TOOL_SEARCH` explicitly to opt in. This feature requires models that support `tool_reference` blocks: Sonnet 4 and later, or Opus 4 and later. Haiku models do not support tool search.

634 928 

635Control tool search behavior with the `ENABLE_TOOL_SEARCH` environment variable:929Control tool search behavior with the `ENABLE_TOOL_SEARCH` environment variable:

636 930 

637| Value | Behavior |931| Value | Behavior |

638| :--------- | :--------------------------------------------------------------------------------- |932| :--------- | :--------------------------------------------------------------------------------------------------------------------------------------------- |

639| `auto` | Activates when MCP tools exceed 10% of context (default) |933| (unset) | All MCP tools deferred and loaded on demand. Falls back to loading upfront on Vertex AI or when `ANTHROPIC_BASE_URL` is a non-first-party host |

640| `auto:<N>` | Activates at custom threshold, where `<N>` is a percentage (e.g., `auto:5` for 5%) |934| `true` | All MCP tools deferred, including on Vertex AI and for non-first-party `ANTHROPIC_BASE_URL` |

641| `true` | Always enabled |935| `auto` | Threshold mode: tools load upfront if they fit within 10% of the context window, deferred otherwise |

642| `false` | Disabled, all MCP tools loaded upfront |936| `auto:<N>` | Threshold mode with a custom percentage, where `<N>` is 0-100 (e.g., `auto:5` for 5%) |

937| `false` | All MCP tools loaded upfront, no deferral |

643 938 

644```bash theme={null}939```bash theme={null}

645# Use a custom 5% threshold940# Use a custom 5% threshold


651 946 

652Or set the value in your [settings.json `env` field](/en/settings#available-settings).947Or set the value in your [settings.json `env` field](/en/settings#available-settings).

653 948 

654You can also disable the MCPSearch tool specifically using the `disallowedTools` setting:949You can also disable the `ToolSearch` tool specifically:

655 950 

656```json theme={null}951```json theme={null}

657{952{

658 "permissions": {953 "permissions": {

659 "deny": ["MCPSearch"]954 "deny": ["ToolSearch"]

660 }955 }

661}956}

662```957```


673 </Step>968 </Step>

674 969 

675 <Step title="Execute a prompt without arguments">970 <Step title="Execute a prompt without arguments">

676 ```971 ```text theme={null}

677 > /mcp__github__list_prs972 /mcp__github__list_prs

678 ```973 ```

679 </Step>974 </Step>

680 975 

681 <Step title="Execute a prompt with arguments">976 <Step title="Execute a prompt with arguments">

682 Many prompts accept arguments. Pass them space-separated after the command:977 Many prompts accept arguments. Pass them space-separated after the command:

683 978 

684 ```979 ```text theme={null}

685 > /mcp__github__pr_review 456980 /mcp__github__pr_review 456

686 ```981 ```

687 982 

688 ```983 ```text theme={null}

689 > /mcp__jira__create_issue "Bug in login flow" high984 /mcp__jira__create_issue "Bug in login flow" high

690 ```985 ```

691 </Step>986 </Step>

692</Steps>987</Steps>

memory.md +285 −110

Details

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> 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.3> Use this file to discover all available pages before exploring further.

4 4 

5# Manage Claude's memory5# How Claude remembers your project

6 6 

7> Learn how to manage Claude Code's memory across sessions with different memory locations and best practices.7> Give Claude persistent instructions with CLAUDE.md files, and let Claude accumulate learnings automatically with auto memory.

8 8 

9Claude Code can remember your preferences across sessions, like style guidelines and common commands in your workflow.9Each Claude Code session begins with a fresh context window. Two mechanisms carry knowledge across sessions:

10 10 

11## Determine memory type11* **CLAUDE.md files**: instructions you write to give Claude persistent context

12* **Auto memory**: notes Claude writes itself based on your corrections and preferences

12 13 

13Claude Code offers four memory locations in a hierarchical structure, each serving a different purpose:14This page covers how to:

14 15 

15| Memory Type | Location | Purpose | Use Case Examples | Shared With |16* [Write and organize CLAUDE.md files](#claude-md-files)

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

17| **Managed policy** | • macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md`<br />• Linux: `/etc/claude-code/CLAUDE.md`<br />• Windows: `C:\Program Files\ClaudeCode\CLAUDE.md` | Organization-wide instructions managed by IT/DevOps | Company coding standards, security policies, compliance requirements | All users in organization |18* [Configure auto memory](#auto-memory) so Claude takes notes automatically

18| **Project memory** | `./CLAUDE.md` or `./.claude/CLAUDE.md` | Team-shared instructions for the project | Project architecture, coding standards, common workflows | Team members via source control |19* [Troubleshoot](#troubleshoot-memory-issues) when instructions aren't being followed

19| **Project rules** | `./.claude/rules/*.md` | Modular, topic-specific project instructions | Language-specific guidelines, testing conventions, API standards | Team members via source control |

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

21| **Project memory (local)** | `./CLAUDE.local.md` | Personal project-specific preferences | Your sandbox URLs, preferred test data | Just you (current project) |

22 20 

23All memory files are automatically loaded into Claude Code's context when launched. Files higher in the hierarchy take precedence and are loaded first, providing a foundation that more specific memories build upon.21## CLAUDE.md vs auto memory

24 22 

25<Note>23Claude Code has two complementary memory systems. Both are loaded at the start of every conversation. Claude treats them as context, not enforced configuration. The more specific and concise your instructions, the more consistently Claude follows them.

26 CLAUDE.local.md files are automatically added to .gitignore, making them ideal for private project-specific preferences that shouldn't be checked into version control.

27</Note>

28 24 

29## CLAUDE.md imports25| | CLAUDE.md files | Auto memory |

26| :------------------- | :------------------------------------------------ | :--------------------------------------------------------------- |

27| **Who writes it** | You | Claude |

28| **What it contains** | Instructions and rules | Learnings and patterns |

29| **Scope** | Project, user, or org | Per working tree |

30| **Loaded into** | Every session | Every session (first 200 lines or 25KB) |

31| **Use for** | Coding standards, workflows, project architecture | Build commands, debugging insights, preferences Claude discovers |

30 32 

31CLAUDE.md files can import additional files using `@path/to/import` syntax. The following example imports 3 files:33Use CLAUDE.md files when you want to guide Claude's behavior. Auto memory lets Claude learn from your corrections without manual effort.

32 34 

33```35Subagents can also maintain their own auto memory. See [subagent configuration](/en/sub-agents#enable-persistent-memory) for details.

36 

37## CLAUDE.md files

38 

39CLAUDE.md files are markdown files that give Claude persistent instructions for a project, your personal workflow, or your entire organization. You write these files in plain text; Claude reads them at the start of every session.

40 

41### When to add to CLAUDE.md

42 

43Treat CLAUDE.md as the place you write down what you'd otherwise re-explain. Add to it when:

44 

45* Claude makes the same mistake a second time

46* A code review catches something Claude should have known about this codebase

47* You type the same correction or clarification into chat that you typed last session

48* A new teammate would need the same context to be productive

49 

50Keep it to facts Claude should hold in every session: build commands, conventions, project layout, "always do X" rules. If an entry is a multi-step procedure or only matters for one part of the codebase, move it to a [skill](/en/skills) or a [path-scoped rule](#organize-rules-with-claude/rules/) instead. The [extension overview](/en/features-overview#build-your-setup-over-time) covers when to use each mechanism.

51 

52### Choose where to put CLAUDE.md files

53 

54CLAUDE.md files can live in several locations, each with a different scope. More specific locations take precedence over broader ones.

55 

56| Scope | Location | Purpose | Use case examples | Shared with |

57| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------- |

58| **Managed policy** | • macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md`<br />• Linux and WSL: `/etc/claude-code/CLAUDE.md`<br />• Windows: `C:\Program Files\ClaudeCode\CLAUDE.md` | Organization-wide instructions managed by IT/DevOps | Company coding standards, security policies, compliance requirements | All users in organization |

59| **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 |

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

61| **Local instructions** | `./CLAUDE.local.md` | Personal project-specific preferences; add to `.gitignore` | Your sandbox URLs, preferred test data | Just you (current project) |

62 

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

64 

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

66 

67### Set up a project CLAUDE.md

68 

69A project CLAUDE.md can be stored in either `./CLAUDE.md` or `./.claude/CLAUDE.md`. Create this file and add instructions that apply to anyone working on the project: build and test commands, coding standards, architectural decisions, naming conventions, and common workflows. These instructions are shared with your team through version control, so focus on project-level standards rather than personal preferences.

70 

71<Tip>

72 Run `/init` to generate a starting CLAUDE.md automatically. Claude analyzes your codebase and creates a file with build commands, test instructions, and project conventions it discovers. If a CLAUDE.md already exists, `/init` suggests improvements rather than overwriting it. Refine from there with instructions Claude wouldn't discover on its own.

73 

74 Set `CLAUDE_CODE_NEW_INIT=1` to enable an interactive multi-phase flow. `/init` asks which artifacts to set up: CLAUDE.md files, skills, and hooks. It then explores your codebase with a subagent, fills in gaps via follow-up questions, and presents a reviewable proposal before writing any files.

75</Tip>

76 

77### Write effective instructions

78 

79CLAUDE.md files are loaded into the context window at the start of every session, consuming tokens alongside your conversation. The [context window visualization](/en/context-window) shows where CLAUDE.md loads relative to the rest of the startup context. Because they're context rather than enforced configuration, how you write instructions affects how reliably Claude follows them. Specific, concise, well-structured instructions work best.

80 

81**Size**: target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence. If your instructions are growing large, use [path-scoped rules](#path-specific-rules) so instructions load only when Claude works with matching files. You can also split content into [imports](#import-additional-files) for organization, though imported files still load and enter the context window at launch.

82 

83**Structure**: use markdown headers and bullets to group related instructions. Claude scans structure the same way readers do: organized sections are easier to follow than dense paragraphs.

84 

85**Specificity**: write instructions that are concrete enough to verify. For example:

86 

87* "Use 2-space indentation" instead of "Format code properly"

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

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

90 

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

92 

93### Import additional files

94 

95CLAUDE.md files can import additional files using `@path/to/import` syntax. Imported files are expanded and loaded into context at launch alongside the CLAUDE.md that references them.

96 

97Both relative and absolute paths are allowed. Relative paths resolve relative to the file containing the import, not the working directory. Imported files can recursively import other files, with a maximum depth of five hops.

98 

99To pull in a README, package.json, and a workflow guide, reference them with `@` syntax anywhere in your CLAUDE.md:

100 

101```text theme={null}

34See @README for project overview and @package.json for available npm commands for this project.102See @README for project overview and @package.json for available npm commands for this project.

35 103 

36# Additional Instructions104# Additional Instructions

37- git workflow @docs/git-instructions.md105- git workflow @docs/git-instructions.md

38```106```

39 107 

40Both relative and absolute paths are allowed. In particular, importing files in user's home dir is a convenient way for your team members to provide individual instructions that are not checked into the repository. Imports are an alternative to CLAUDE.local.md that work better across multiple git worktrees.108For private per-project preferences that shouldn't be checked into version control, create a `CLAUDE.local.md` at the project root. It loads alongside `CLAUDE.md` and is treated the same way. Add `CLAUDE.local.md` to your `.gitignore` so it isn't committed; running `/init` and choosing the personal option does this for you.

41 109 

42```110If you work across multiple git worktrees of the same repository, a gitignored `CLAUDE.local.md` only exists in the worktree where you created it. To share personal instructions across worktrees, import a file from your home directory instead:

111 

112```text theme={null}

43# Individual Preferences113# Individual Preferences

44- @~/.claude/my-project-instructions.md114- @~/.claude/my-project-instructions.md

45```115```

46 116 

47To avoid potential collisions, imports are not evaluated inside markdown code spans and code blocks.117<Warning>

118 The first time Claude Code encounters external imports in a project, it shows an approval dialog listing the files. If you decline, the imports stay disabled and the dialog does not appear again.

119</Warning>

48 120 

49```121For a more structured approach to organizing instructions, see [`.claude/rules/`](#organize-rules-with-claude/rules/).

50This code span will not be treated as an import: `@anthropic-ai/claude-code`

51```

52 122 

53Imported files can recursively import additional files, with a max-depth of 5 hops. You can see what memory files are loaded by running `/memory` command.123### AGENTS.md

54 124 

55## How Claude looks up memories125Claude Code reads `CLAUDE.md`, not `AGENTS.md`. If your repository already uses `AGENTS.md` for other coding agents, create a `CLAUDE.md` that imports it so both tools read the same instructions without duplicating them. You can also add Claude-specific instructions below the import. Claude loads the imported file at session start, then appends the rest:

56 126 

57Claude Code reads memories recursively: starting in the cwd, Claude Code recurses up to (but not including) the root directory */* and reads any CLAUDE.md or CLAUDE.local.md files it finds. This is especially convenient when working in large repositories where you run Claude Code in *foo/bar/*, and have memories in both *foo/CLAUDE.md* and *foo/bar/CLAUDE.md*.127```markdown CLAUDE.md theme={null}

128@AGENTS.md

58 129 

59Claude will also discover CLAUDE.md nested in subtrees under your current working directory. Instead of loading them at launch, they are only included when Claude reads files in those subtrees.130## Claude Code

60 131 

61### Load memory from additional directories132Use plan mode for changes under `src/billing/`.

133```

62 134 

63The `--add-dir` flag gives Claude access to additional directories outside your main working directory. By default, CLAUDE.md files from these directories are not loaded.135### How CLAUDE.md files load

64 136 

65To also load memory files (CLAUDE.md, .claude/CLAUDE.md, and .claude/rules/\*.md) from additional directories, set the `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` environment variable:137Claude Code reads CLAUDE.md files by walking up the directory tree from your current working directory, checking each directory along the way for `CLAUDE.md` and `CLAUDE.local.md` files. This means if you run Claude Code in `foo/bar/`, it loads instructions from `foo/bar/CLAUDE.md`, `foo/CLAUDE.md`, and any `CLAUDE.local.md` files alongside them.

66 138 

67```bash theme={null}139All discovered files are concatenated into context rather than overriding each other. Within each directory, `CLAUDE.local.md` is appended after `CLAUDE.md`, so when instructions conflict, your personal notes are the last thing Claude reads at that level.

68CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared-config

69```

70 140 

71## Directly edit memories with `/memory`141Claude also discovers `CLAUDE.md` and `CLAUDE.local.md` files in subdirectories under your current working directory. Instead of loading them at launch, they are included when Claude reads files in those subdirectories.

72 142 

73Use the `/memory` command during a session to open any memory file in your system editor for more extensive additions or organization.143If 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.

74 144 

75## Set up project memory145Block-level HTML comments (`<!-- maintainer notes -->`) in CLAUDE.md files are stripped before the content is injected into Claude's context. Use them to leave notes for human maintainers without spending context tokens on them. Comments inside code blocks are preserved. When you open a CLAUDE.md file directly with the Read tool, comments remain visible.

76 146 

77Suppose you want to set up a CLAUDE.md file to store important project information, conventions, and frequently used commands. Project memory can be stored in either `./CLAUDE.md` or `./.claude/CLAUDE.md`.147#### Load from additional directories

78 148 

79Bootstrap a CLAUDE.md for your codebase with the following command:149The `--add-dir` flag gives Claude access to additional directories outside your main working directory. By default, CLAUDE.md files from these directories are not loaded.

80 150 

81```151To also load memory files from additional directories, set the `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` environment variable:

82> /init152 

153```bash theme={null}

154CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared-config

83```155```

84 156 

85<Tip>157This loads `CLAUDE.md`, `.claude/CLAUDE.md`, `.claude/rules/*.md`, and `CLAUDE.local.md` from the additional directory. `CLAUDE.local.md` is skipped if you exclude `local` from [`--setting-sources`](/en/cli-reference).

86 Tips:

87 158 

88 * Include frequently used commands (build, test, lint) to avoid repeated searches159### Organize rules with `.claude/rules/`

89 * Document code style preferences and naming conventions

90 * Add important architectural patterns specific to your project

91 * CLAUDE.md memories can be used for both instructions shared with your team and for your individual preferences.

92</Tip>

93 160 

94## Modular rules with `.claude/rules/`161For larger projects, you can organize instructions into multiple files using the `.claude/rules/` directory. This keeps instructions modular and easier for teams to maintain. Rules can also be [scoped to specific file paths](#path-specific-rules), so they only load into context when Claude works with matching files, reducing noise and saving context space.

95 162 

96For larger projects, you can organize instructions into multiple files using the `.claude/rules/` directory. This allows teams to maintain focused, well-organized rule files instead of one large CLAUDE.md.163<Note>

164 Rules load into context every session or when matching files are opened. For task-specific instructions that don't need to be in context all the time, use [skills](/en/skills) instead, which only load when you invoke them or when Claude determines they're relevant to your prompt.

165</Note>

97 166 

98### Basic structure167#### Set up rules

99 168 

100Place markdown files in your project's `.claude/rules/` directory:169Place markdown files in your project's `.claude/rules/` directory. Each file should cover one topic, with a descriptive filename like `testing.md` or `api-design.md`. All `.md` files are discovered recursively, so you can organize rules into subdirectories like `frontend/` or `backend/`:

101 170 

102```171```text theme={null}

103your-project/172your-project/

104├── .claude/173├── .claude/

105│ ├── CLAUDE.md # Main project instructions174│ ├── CLAUDE.md # Main project instructions


109│ └── security.md # Security requirements178│ └── security.md # Security requirements

110```179```

111 180 

112All `.md` files in `.claude/rules/` are automatically loaded as project memory, with the same priority as `.claude/CLAUDE.md`.181Rules without [`paths` frontmatter](#path-specific-rules) are loaded at launch with the same priority as `.claude/CLAUDE.md`.

113 182 

114### Path-specific rules183#### Path-specific rules

115 184 

116Rules can be scoped to specific files using YAML frontmatter with the `paths` field. These conditional rules only apply when Claude is working with files matching the specified patterns.185Rules can be scoped to specific files using YAML frontmatter with the `paths` field. These conditional rules only apply when Claude is working with files matching the specified patterns.

117 186 


128- Include OpenAPI documentation comments197- Include OpenAPI documentation comments

129```198```

130 199 

131Rules without a `paths` field are loaded unconditionally and apply to all files.200Rules without a `paths` field are loaded unconditionally and apply to all files. Path-scoped rules trigger when Claude reads files matching the pattern, not on every tool use.

132 201 

133### Glob patterns202Use glob patterns in the `paths` field to match files by extension, directory, or any combination:

134 

135The `paths` field supports standard glob patterns:

136 203 

137| Pattern | Matches |204| Pattern | Matches |

138| ---------------------- | ---------------------------------------- |205| ---------------------- | ---------------------------------------- |


141| `*.md` | Markdown files in the project root |208| `*.md` | Markdown files in the project root |

142| `src/components/*.tsx` | React components in a specific directory |209| `src/components/*.tsx` | React components in a specific directory |

143 210 

144You can specify multiple patterns:211You can specify multiple patterns and use brace expansion to match multiple extensions in one pattern:

145 212 

146```markdown theme={null}213```markdown theme={null}

147---214---

148paths:215paths:

149 - "src/**/*.ts"216 - "src/**/*.{ts,tsx}"

150 - "lib/**/*.ts"217 - "lib/**/*.ts"

151 - "tests/**/*.test.ts"218 - "tests/**/*.test.ts"

152---219---

153```220```

154 221 

155Brace expansion is supported for matching multiple extensions or directories:222#### Share rules across projects with symlinks

156 223 

157```markdown theme={null}224The `.claude/rules/` directory supports symlinks, so you can maintain a shared set of rules and link them into multiple projects. Symlinks are resolved and loaded normally, and circular symlinks are detected and handled gracefully.

158paths:

159 - "src/**/*.{ts,tsx}"

160 - "{src,lib}/**/*.ts"

161 225 

162# TypeScript/React Rules226This example links both a shared directory and an individual file:

163```

164 227 

165This expands `src/**/*.{ts,tsx}` to match both `.ts` and `.tsx` files.228```bash theme={null}

229ln -s ~/shared-claude-rules .claude/rules/shared

230ln -s ~/company-standards/security.md .claude/rules/security.md

231```

166 232 

167### Subdirectories233#### User-level rules

168 234 

169Rules can be organized into subdirectories for better structure:235Personal rules in `~/.claude/rules/` apply to every project on your machine. Use them for preferences that aren't project-specific:

170 236 

237```text theme={null}

238~/.claude/rules/

239├── preferences.md # Your personal coding preferences

240└── workflows.md # Your preferred workflows

171```241```

172.claude/rules/242 

173├── frontend/243User-level rules are loaded before project rules, giving project rules higher priority.

174│ ├── react.md244 

175│ └── styles.md245### Manage CLAUDE.md for large teams

176├── backend/246 

177│ ├── api.md247For organizations deploying Claude Code across teams, you can centralize instructions and control which CLAUDE.md files are loaded.

178│ └── database.md248 

179└── general.md249#### Deploy organization-wide CLAUDE.md

250 

251Organizations can deploy a centrally managed CLAUDE.md that applies to all users on a machine. This file cannot be excluded by individual settings.

252 

253<Steps>

254 <Step title="Create the file at the managed policy location">

255 * macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md`

256 * Linux and WSL: `/etc/claude-code/CLAUDE.md`

257 * Windows: `C:\Program Files\ClaudeCode\CLAUDE.md`

258 </Step>

259 

260 <Step title="Deploy with your configuration management system">

261 Use MDM, Group Policy, Ansible, or similar tools to distribute the file across developer machines. See [managed settings](/en/permissions#managed-settings) for other organization-wide configuration options.

262 </Step>

263</Steps>

264 

265A managed CLAUDE.md and [managed settings](/en/settings#settings-files) serve different purposes. Use settings for technical enforcement and CLAUDE.md for behavioral guidance:

266 

267| Concern | Configure in |

268| :--------------------------------------------- | :-------------------------------------------------------- |

269| Block specific tools, commands, or file paths | Managed settings: `permissions.deny` |

270| Enforce sandbox isolation | Managed settings: `sandbox.enabled` |

271| Environment variables and API provider routing | Managed settings: `env` |

272| Authentication method and organization lock | Managed settings: `forceLoginMethod`, `forceLoginOrgUUID` |

273| Code style and quality guidelines | Managed CLAUDE.md |

274| Data handling and compliance reminders | Managed CLAUDE.md |

275| Behavioral instructions for Claude | Managed CLAUDE.md |

276 

277Settings rules are enforced by the client regardless of what Claude decides to do. CLAUDE.md instructions shape Claude's behavior but are not a hard enforcement layer.

278 

279#### Exclude specific CLAUDE.md files

280 

281In large monorepos, ancestor CLAUDE.md files may contain instructions that aren't relevant to your work. The `claudeMdExcludes` setting lets you skip specific files by path or glob pattern.

282 

283This example excludes a top-level CLAUDE.md and a rules directory from a parent folder. Add it to `.claude/settings.local.json` so the exclusion stays local to your machine:

284 

285```json theme={null}

286{

287 "claudeMdExcludes": [

288 "**/monorepo/CLAUDE.md",

289 "/home/user/monorepo/other-team/.claude/rules/**"

290 ]

291}

180```292```

181 293 

182All `.md` files are discovered recursively.294Patterns are matched against absolute file paths using glob syntax. You can configure `claudeMdExcludes` at any [settings layer](/en/settings#settings-files): user, project, local, or managed policy. Arrays merge across layers.

183 295 

184### Symlinks296Managed policy CLAUDE.md files cannot be excluded. This ensures organization-wide instructions always apply regardless of individual settings.

185 297 

186The `.claude/rules/` directory supports symlinks, allowing you to share common rules across multiple projects:298## Auto memory

187 299 

188```bash theme={null}300Auto memory lets Claude accumulate knowledge across sessions without you writing anything. Claude saves notes for itself as it works: build commands, debugging insights, architecture notes, code style preferences, and workflow habits. Claude doesn't save something every session. It decides what's worth remembering based on whether the information would be useful in a future conversation.

189# Symlink a shared rules directory

190ln -s ~/shared-claude-rules .claude/rules/shared

191 301 

192# Symlink individual rule files302<Note>

193ln -s ~/company-standards/security.md .claude/rules/security.md303 Auto memory requires Claude Code v2.1.59 or later. Check your version with `claude --version`.

304</Note>

305 

306### Enable or disable auto memory

307 

308Auto memory is on by default. To toggle it, open `/memory` in a session and use the auto memory toggle, or set `autoMemoryEnabled` in your project settings:

309 

310```json theme={null}

311{

312 "autoMemoryEnabled": false

313}

194```314```

195 315 

196Symlinks are resolved and their contents are loaded normally. Circular symlinks are detected and handled gracefully.316To disable auto memory via environment variable, set `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1`.

317 

318### Storage location

197 319 

198### User-level rules320Each project gets its own memory directory at `~/.claude/projects/<project>/memory/`. The `<project>` path is derived from the git repository, so all worktrees and subdirectories within the same repo share one auto memory directory. Outside a git repo, the project root is used instead.

199 321 

200You can create personal rules that apply to all your projects in `~/.claude/rules/`:322To store auto memory in a different location, set `autoMemoryDirectory` in your user or local settings:

201 323 

324```json theme={null}

325{

326 "autoMemoryDirectory": "~/my-custom-memory-dir"

327}

202```328```

203~/.claude/rules/329 

204├── preferences.md # Your personal coding preferences330This setting is accepted from policy, local, and user settings. It is not accepted from project settings (`.claude/settings.json`) to prevent a shared project from redirecting auto memory writes to sensitive locations.

205└── workflows.md # Your preferred workflows331 

332The directory contains a `MEMORY.md` entrypoint and optional topic files:

333 

334```text theme={null}

335~/.claude/projects/<project>/memory/

336├── MEMORY.md # Concise index, loaded into every session

337├── debugging.md # Detailed notes on debugging patterns

338├── api-conventions.md # API design decisions

339└── ... # Any other topic files Claude creates

206```340```

207 341 

208User-level rules are loaded before project rules, giving project rules higher priority.342`MEMORY.md` acts as an index of the memory directory. Claude reads and writes files in this directory throughout your session, using `MEMORY.md` to keep track of what's stored where.

209 343 

210<Tip>344Auto memory is machine-local. All worktrees and subdirectories within the same git repository share one auto memory directory. Files are not shared across machines or cloud environments.

211 Best practices for `.claude/rules/`:345 

346### How it works

347 

348The first 200 lines of `MEMORY.md`, or the first 25KB, whichever comes first, are loaded at the start of every conversation. Content beyond that threshold is not loaded at session start. Claude keeps `MEMORY.md` concise by moving detailed notes into separate topic files.

349 

350This limit applies only to `MEMORY.md`. CLAUDE.md files are loaded in full regardless of length, though shorter files produce better adherence.

351 

352Topic files like `debugging.md` or `patterns.md` are not loaded at startup. Claude reads them on demand using its standard file tools when it needs the information.

353 

354Claude reads and writes memory files during your session. When you see "Writing memory" or "Recalled memory" in the Claude Code interface, Claude is actively updating or reading from `~/.claude/projects/<project>/memory/`.

355 

356### Audit and edit your memory

357 

358Auto memory files are plain markdown you can edit or delete at any time. Run [`/memory`](#view-and-edit-with-memory) to browse and open memory files from within a session.

212 359 

213 * **Keep rules focused**: Each file should cover one topic (e.g., `testing.md`, `api-design.md`)360## View and edit with `/memory`

214 * **Use descriptive filenames**: The filename should indicate what the rules cover361 

215 * **Use conditional rules sparingly**: Only add `paths` frontmatter when rules truly apply to specific file types362The `/memory` command lists all CLAUDE.md, CLAUDE.local.md, and rules files loaded in your current session, lets you toggle auto memory on or off, and provides a link to open the auto memory folder. Select any file to open it in your editor.

216 * **Organize with subdirectories**: Group related rules (e.g., `frontend/`, `backend/`)363 

364When you ask Claude to remember something, like "always use pnpm, not npm" or "remember that the API tests require a local Redis instance," Claude saves it to auto memory. To add instructions to CLAUDE.md instead, ask Claude directly, like "add this to CLAUDE.md," or edit the file yourself via `/memory`.

365 

366## Troubleshoot memory issues

367 

368These are the most common issues with CLAUDE.md and auto memory, along with steps to debug them.

369 

370### Claude isn't following my CLAUDE.md

371 

372CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself. Claude reads it and tries to follow it, but there's no guarantee of strict compliance, especially for vague or conflicting instructions.

373 

374To debug:

375 

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

377* 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)).

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

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

380 

381For instructions you want at the system prompt level, use [`--append-system-prompt`](/en/cli-reference#system-prompt-flags). This must be passed every invocation, so it's better suited to scripts and automation than interactive use.

382 

383<Tip>

384 Use the [`InstructionsLoaded` hook](/en/hooks#instructionsloaded) to log exactly which instruction files are loaded, when they load, and why. This is useful for debugging path-specific rules or lazy-loaded files in subdirectories.

217</Tip>385</Tip>

218 386 

219## Organization-level memory management387### I don't know what auto memory saved

388 

389Run `/memory` and select the auto memory folder to browse what Claude has saved. Everything is plain markdown you can read, edit, or delete.

390 

391### My CLAUDE.md is too large

392 

393Files over 200 lines consume more context and may reduce adherence. Use [path-scoped rules](#path-specific-rules) to load instructions only when Claude works with matching files, or trim content that isn't needed in every session. Splitting into [`@path` imports](#import-additional-files) helps organization but does not reduce context, since imported files load at launch.

220 394 

221Organizations can deploy centrally managed CLAUDE.md files that apply to all users.395### Instructions seem lost after `/compact`

222 396 

223To set up organization-level memory management:397Project-root CLAUDE.md survives compaction: after `/compact`, Claude re-reads it from disk and re-injects it into the session. Nested CLAUDE.md files in subdirectories are not re-injected automatically; they reload the next time Claude reads a file in that subdirectory.

224 398 

2251. Create the managed memory file at the **Managed policy** location shown in the [memory types table above](#determine-memory-type).399If an instruction disappeared after compaction, it was either given only in conversation or lives in a nested CLAUDE.md that hasn't reloaded yet. Add conversation-only instructions to CLAUDE.md to make them persist. See [What survives compaction](/en/context-window#what-survives-compaction) for the full breakdown.

226 400 

2272. Deploy via your configuration management system (MDM, Group Policy, Ansible, etc.) to ensure consistent distribution across all developer machines.401See [Write effective instructions](#write-effective-instructions) for guidance on size, structure, and specificity.

228 402 

229## Memory best practices403## Related resources

230 404 

231* **Be specific**: "Use 2-space indentation" is better than "Format code properly".405* [Debug your configuration](/en/debug-your-config): diagnose why CLAUDE.md or settings aren't taking effect

232* **Use structure to organize**: Format each individual memory as a bullet point and group related memories under descriptive markdown headings.406* [Skills](/en/skills): package repeatable workflows that load on demand

233* **Review periodically**: Update memories as your project evolves to ensure Claude is always using the most up to date information and context.407* [Settings](/en/settings): configure Claude Code behavior with settings files

408* [Subagent memory](/en/sub-agents#enable-persistent-memory): let subagents maintain their own auto memory

Details

6 6 

7> Learn about configuring Claude Code through Microsoft Foundry, including setup, configuration, and troubleshooting.7> Learn about configuring Claude Code through Microsoft Foundry, including setup, configuration, and troubleshooting.

8 8 

9 

10 

11<Experiment flag="docs-contact-sales-cta" treatment={<ContactSalesCard surface="foundry" />} />

12 

9## Prerequisites13## Prerequisites

10 14 

11Before configuring Claude Code with Microsoft Foundry, ensure you have:15Before configuring Claude Code with Microsoft Foundry, ensure you have:


14* RBAC permissions to create Microsoft Foundry resources and deployments18* RBAC permissions to create Microsoft Foundry resources and deployments

15* Azure CLI installed and configured (optional - only needed if you don't have another mechanism for getting credentials)19* Azure CLI installed and configured (optional - only needed if you don't have another mechanism for getting credentials)

16 20 

21<Note>

22 If you are deploying Claude Code to multiple users, [pin your model versions](#4-pin-model-versions) to prevent breakage when Anthropic releases new models.

23</Note>

24 

17## Setup25## Setup

18 26 

19### 1. Provision Microsoft Foundry resource27### 1. Provision Microsoft Foundry resource


59 67 

60### 3. Configure Claude Code68### 3. Configure Claude Code

61 69 

62Set the following environment variables to enable Microsoft Foundry. Note that your deployments' names are set as the model identifiers in Claude Code (may be optional if using suggested deployment names).70Set the following environment variables to enable Microsoft Foundry:

63 71 

64```bash theme={null}72```bash theme={null}

65# Enable Microsoft Foundry integration73# Enable Microsoft Foundry integration


69export ANTHROPIC_FOUNDRY_RESOURCE={resource}77export ANTHROPIC_FOUNDRY_RESOURCE={resource}

70# Or provide the full base URL:78# Or provide the full base URL:

71# export ANTHROPIC_FOUNDRY_BASE_URL=https://{resource}.services.ai.azure.com/anthropic79# export ANTHROPIC_FOUNDRY_BASE_URL=https://{resource}.services.ai.azure.com/anthropic

80```

81 

82### 4. Pin model versions

72 83 

73# Set models to your resource's deployment names84<Warning>

74export ANTHROPIC_DEFAULT_SONNET_MODEL='claude-sonnet-4-5'85 Pin specific model versions for every deployment. If you use model aliases (`sonnet`, `opus`, `haiku`) without pinning, Claude Code may attempt to use a newer model version that isn't available in your Foundry account, breaking existing users when Anthropic releases updates. When you create Azure deployments, select a specific model version rather than "auto-update to latest."

86</Warning>

87 

88Set the model variables to match the deployment names you created in step 1.

89 

90Without `ANTHROPIC_DEFAULT_OPUS_MODEL`, the `opus` alias on Foundry resolves to Opus 4.6. Set it to the Opus 4.7 ID to use the latest model:

91 

92```bash theme={null}

93export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7'

94export ANTHROPIC_DEFAULT_SONNET_MODEL='claude-sonnet-4-6'

75export ANTHROPIC_DEFAULT_HAIKU_MODEL='claude-haiku-4-5'95export ANTHROPIC_DEFAULT_HAIKU_MODEL='claude-haiku-4-5'

76export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-1'

77```96```

78 97 

79For more details on model configuration options, see [Model configuration](/en/model-config).98For current and legacy model IDs, see [Models overview](https://platform.claude.com/docs/en/about-claude/models/overview). See [Model configuration](/en/model-config#pin-models-for-third-party-deployments) for the full list of environment variables.

99 

100[Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) is enabled automatically. To request a 1-hour cache TTL instead of the 5-minute default, set the following variable; cache writes with a 1-hour TTL are billed at a higher rate:

101 

102```bash theme={null}

103export ENABLE_PROMPT_CACHING_1H=1

104```

80 105 

81## Azure RBAC configuration106## Azure RBAC configuration

82 107 

model-config.md +277 −21

Details

12 12 

13* A **model alias**13* A **model alias**

14* A **model name**14* A **model name**

15 * Anthropic API: A full **[model name](https://docs.claude.com/en/docs/about-claude/models/overview#model-names)**15 * Anthropic API: A full **[model name](https://platform.claude.com/docs/en/about-claude/models/overview)**

16 * Bedrock: an inference profile ARN16 * Bedrock: an inference profile ARN

17 * Foundry: a deployment name17 * Foundry: a deployment name

18 * Vertex: a version name18 * Vertex: a version name


23remembering exact version numbers:23remembering exact version numbers:

24 24 

25| Model alias | Behavior |25| Model alias | Behavior |

26| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |26| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

27| **`default`** | Recommended model setting, depending on your account type |27| **`default`** | Special value that clears any model override and reverts to the recommended model for your account type. Not itself a model alias |

28| **`sonnet`** | Uses the latest Sonnet model (currently Sonnet 4.5) for daily coding tasks |28| **`best`** | Uses the most capable available model, currently equivalent to `opus` |

29| **`opus`** | Uses Opus model (currently Opus 4.5) for specialized complex reasoning tasks |29| **`sonnet`** | Uses the latest Sonnet model for daily coding tasks |

30| **`opus`** | Uses the latest Opus model for complex reasoning tasks |

30| **`haiku`** | Uses the fast and efficient Haiku model for simple tasks |31| **`haiku`** | Uses the fast and efficient Haiku model for simple tasks |

31| **`sonnet[1m]`** | Uses Sonnet with a [1 million token context window](https://docs.claude.com/en/docs/build-with-claude/context-windows#1m-token-context-window) window for long sessions |32| **`sonnet[1m]`** | Uses Sonnet with a [1 million token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#1m-token-context-window) for long sessions |

33| **`opus[1m]`** | Uses Opus with a [1 million token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#1m-token-context-window) for long sessions |

32| **`opusplan`** | Special mode that uses `opus` during plan mode, then switches to `sonnet` for execution |34| **`opusplan`** | Special mode that uses `opus` during plan mode, then switches to `sonnet` for execution |

33 35 

36On the Anthropic API, `opus` resolves to Opus 4.7 and `sonnet` resolves to Sonnet 4.6. On Bedrock, Vertex, and Foundry, `opus` resolves to Opus 4.6 and `sonnet` resolves to Sonnet 4.5; newer models are available on those providers by selecting the full model name explicitly or setting `ANTHROPIC_DEFAULT_OPUS_MODEL` or `ANTHROPIC_DEFAULT_SONNET_MODEL`.

37 

38Aliases point to the recommended version for your provider and update over time. To pin to a specific version, use the full model name (for example, `claude-opus-4-7`) or set the corresponding environment variable like `ANTHROPIC_DEFAULT_OPUS_MODEL`.

39 

40<Note>

41 Opus 4.7 requires Claude Code v2.1.111 or later. Run `claude update` to upgrade.

42</Note>

43 

34### Setting your model44### Setting your model

35 45 

36You can configure your model in several ways, listed in order of priority:46You can configure your model in several ways, listed in order of priority:

37 47 

381. **During session** - Use `/model <alias|name>` to switch models mid-session481. **During session** - Use `/model <alias|name>` to switch immediately, or run `/model` with no argument to open the picker. The picker asks for confirmation when the conversation has prior output, since the next response re-reads the full history without cached context

392. **At startup** - Launch with `claude --model <alias|name>`492. **At startup** - Launch with `claude --model <alias|name>`

403. **Environment variable** - Set `ANTHROPIC_MODEL=<alias|name>`503. **Environment variable** - Set `ANTHROPIC_MODEL=<alias|name>`

414. **Settings** - Configure permanently in your settings file using the `model`514. **Settings** - Configure permanently in your settings file using the `model`

42 field.52 field.

43 53 

54Your `/model` selection is saved to user settings and persists across restarts. As of v2.1.117, if the project's `.claude/settings.json` pins a different model, Claude Code also writes your choice to `.claude/settings.local.json` so it continues to apply in that project after a restart. Managed settings take precedence and reapply on the next launch.

55 

56When the active model at startup comes from project or managed settings rather than your own selection, the startup header shows which settings file set it. Run `/model` to override for the current session.

57 

44Example usage:58Example usage:

45 59 

46```bash theme={null}60```bash theme={null}


53 67 

54Example settings file:68Example settings file:

55 69 

56```70```json theme={null}

57{71{

58 "permissions": {72 "permissions": {

59 ...73 ...


62}76}

63```77```

64 78 

79## Restrict model selection

80 

81Enterprise administrators can use `availableModels` in [managed or policy settings](/en/settings#settings-files) to restrict which models users can select.

82 

83When `availableModels` is set, users cannot switch to models not in the list via `/model`, `--model` flag, or `ANTHROPIC_MODEL` environment variable.

84 

85```json theme={null}

86{

87 "availableModels": ["sonnet", "haiku"]

88}

89```

90 

91### Default model behavior

92 

93The Default option in the model picker is not affected by `availableModels`. It always remains available and represents the system's runtime default [based on the user's subscription tier](#default-model-setting).

94 

95Even with `availableModels: []`, users can still use Claude Code with the Default model for their tier.

96 

97### Control the model users run on

98 

99The `model` setting is an initial selection, not enforcement. It sets which model is active when a session starts, but users can still open `/model` and pick Default, which resolves to the system default for their tier regardless of what `model` is set to.

100 

101To fully control the model experience, combine three settings:

102 

103* **`availableModels`**: restricts which named models users can switch to

104* **`model`**: sets the initial model selection when a session starts

105* **`ANTHROPIC_DEFAULT_SONNET_MODEL`** / **`ANTHROPIC_DEFAULT_OPUS_MODEL`** / **`ANTHROPIC_DEFAULT_HAIKU_MODEL`**: control what the Default option and the `sonnet`, `opus`, and `haiku` aliases resolve to

106 

107This example starts users on Sonnet 4.5, limits the picker to Sonnet and Haiku, and pins Default to resolve to Sonnet 4.5 rather than the latest release:

108 

109```json theme={null}

110{

111 "model": "claude-sonnet-4-5",

112 "availableModels": ["claude-sonnet-4-5", "haiku"],

113 "env": {

114 "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-5"

115 }

116}

117```

118 

119Without the `env` block, a user who selects Default in the picker would get the latest Sonnet release, bypassing the version pin in `model` and `availableModels`.

120 

121### Merge behavior

122 

123When `availableModels` is set at multiple levels, such as user settings and project settings, arrays are merged and deduplicated. To enforce a strict allowlist, set `availableModels` in managed or policy settings which take highest priority.

124 

125### Mantle model IDs

126 

127When the [Bedrock Mantle endpoint](/en/amazon-bedrock#use-the-mantle-endpoint) is enabled, entries in `availableModels` that start with `anthropic.` are added to the `/model` picker as custom options and routed to the Mantle endpoint. This is an exception to the alias-only matching described in [Pin models for third-party deployments](#pin-models-for-third-party-deployments). The setting still restricts the picker to listed entries, so include the standard aliases alongside any Mantle IDs.

128 

65## Special model behavior129## Special model behavior

66 130 

67### `default` model setting131### `default` model setting

68 132 

69The behavior of `default` depends on your account type.133The behavior of `default` depends on your account type:

134 

135* **Max and Team Premium**: defaults to Opus 4.7

136* **Pro, Team Standard, Enterprise, and Anthropic API**: defaults to Sonnet 4.6

137* **Bedrock, Vertex, and Foundry**: defaults to Sonnet 4.5

138 

139Claude Code may automatically fall back to Sonnet if you hit a usage threshold with Opus.

70 140 

71For certain Max users, Claude Code will automatically fall back to Sonnet if you141<Note>

72hit a usage threshold with Opus.142 On April 23, 2026, the default model for Enterprise pay-as-you-go and Anthropic API users will change to Opus 4.7. To keep a different default, set `ANTHROPIC_MODEL` or the `model` field in [server-managed settings](/en/server-managed-settings).

143</Note>

73 144 

74### `opusplan` model setting145### `opusplan` model setting

75 146 


83This gives you the best of both worlds: Opus's superior reasoning for planning,154This gives you the best of both worlds: Opus's superior reasoning for planning,

84and Sonnet's efficiency for execution.155and Sonnet's efficiency for execution.

85 156 

86### Extended context with \[1m]157The plan-mode Opus phase runs with the standard 200K context window. The automatic 1M upgrade described in [Extended context](#extended-context) applies to the `opus` model setting and does not extend to `opusplan`.

158 

159### Adjust effort level

160 

161[Effort levels](https://platform.claude.com/docs/en/build-with-claude/effort) control adaptive reasoning, which lets the model decide whether and how much to think on each step based on task complexity. Lower effort is faster and cheaper for straightforward tasks, while higher effort provides deeper reasoning for complex problems.

162 

163Effort is supported on Opus 4.7, Opus 4.6, and Sonnet 4.6. The available levels depend on the model:

164 

165| Model | Levels |

166| :---------------------- | :-------------------------------------- |

167| Opus 4.7 | `low`, `medium`, `high`, `xhigh`, `max` |

168| Opus 4.6 and Sonnet 4.6 | `low`, `medium`, `high`, `max` |

169 

170If you set a level the active model does not support, Claude Code falls back to the highest supported level at or below the one you set. For example, `xhigh` runs as `high` on Opus 4.6.

171 

172As of v2.1.117, the default effort is `xhigh` on Opus 4.7 and `high` on Opus 4.6 and Sonnet 4.6.

173 

174When you first run Opus 4.7, Claude Code applies `xhigh` even if you previously set a different effort level for Opus 4.6 or Sonnet 4.6. Run `/effort` again to choose a different level after switching.

175 

176`low`, `medium`, `high`, and `xhigh` persist across sessions. `max` provides the deepest reasoning with no constraint on token spending and applies to the current session only, except when set through the `CLAUDE_CODE_EFFORT_LEVEL` environment variable.

177 

178#### Choose an effort level

179 

180Each level trades token spend against capability. The default suits most coding tasks; adjust when you want a different balance.

181 

182| Level | When to use it |

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

184| `low` | Reserve for short, scoped, latency-sensitive tasks that are not intelligence-sensitive |

185| `medium` | Reduces token usage for cost-sensitive work that can trade off some intelligence |

186| `high` | Balances token usage and intelligence. Use as a minimum for intelligence-sensitive work, or to reduce token spend relative to `xhigh` |

187| `xhigh` | Best results for most coding and agentic tasks. Recommended default on Opus 4.7 |

188| `max` | Can improve performance on demanding tasks but may show diminishing returns and is prone to overthinking. Test before adopting broadly |

189 

190The effort scale is calibrated per model, so the same level name does not represent the same underlying value across models.

191 

192For one-off deep reasoning without changing your session setting, include "ultrathink" in your prompt. This adds an in-context instruction telling the model to reason more on that turn; it does not change the effort level sent to the API.

193 

194#### Set the effort level

195 

196You can change effort through any of the following:

197 

198* **`/effort`**: run `/effort` with no arguments to open an interactive slider, `/effort` followed by a level name to set it directly, or `/effort auto` to reset to the model default

199* **In `/model`**: use left/right arrow keys to adjust the effort slider when selecting a model

200* **`--effort` flag**: pass a level name to set it for a single session when launching Claude Code

201* **Environment variable**: set `CLAUDE_CODE_EFFORT_LEVEL` to a level name or `auto`

202* **Settings**: set `effortLevel` in your settings file

203* **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

204 

205The 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.

206 

207The 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`.

208 

209#### Adaptive reasoning and fixed thinking budgets

210 

211Adaptive reasoning makes thinking optional on each step, so Claude can respond faster to routine prompts and reserve deeper thinking for steps that benefit from it. If you want Claude to think more or less often than the current level produces, you can say so directly in your prompt or in `CLAUDE.md`; the model responds to that guidance within its effort setting.

212 

213Opus 4.7 always uses adaptive reasoning. The fixed thinking budget mode and `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` do not apply to it.

214 

215On Opus 4.6 and Sonnet 4.6, you can set `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1` to revert to the previous fixed thinking budget controlled by `MAX_THINKING_TOKENS`. See [environment variables](/en/env-vars).

216 

217### Extended context

87 218 

88For Console/API users, the `[1m]` suffix can be added to full model names to219Opus 4.7, Opus 4.6, and Sonnet 4.6 support a [1 million token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#1m-token-context-window) for long sessions with large codebases.

89enable a220 

90[1 million token context window](https://docs.claude.com/en/docs/build-with-claude/context-windows#1m-token-context-window).221Availability varies by model and plan. On Max, Team, and Enterprise plans, Opus is automatically upgraded to 1M context with no additional configuration. This applies to both Team Standard and Team Premium seats.

222 

223| Plan | Opus with 1M context | Sonnet with 1M context |

224| ------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |

225| Max, Team, and Enterprise | Included with subscription | Requires [extra usage](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |

226| Pro | Requires [extra usage](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) | Requires [extra usage](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |

227| API and pay-as-you-go | Full access | Full access |

228 

229To disable 1M context entirely, set `CLAUDE_CODE_DISABLE_1M_CONTEXT=1`. This removes 1M model variants from the model picker. See [environment variables](/en/env-vars).

230 

231The 1M context window uses standard model pricing with no premium for tokens beyond 200K. For plans where extended context is included with your subscription, usage remains covered by your subscription. For plans that access extended context through extra usage, tokens are billed to extra usage.

232 

233If your account supports 1M context, the option appears in the model picker (`/model`) in the latest versions of Claude Code. If you don't see it, try restarting your session.

234 

235You can also use the `[1m]` suffix with model aliases or full model names:

91 236 

92```bash theme={null}237```bash theme={null}

93# Example of using a full model name with the [1m] suffix238# Use the opus[1m] or sonnet[1m] alias

94/model anthropic.claude-sonnet-4-5-20250929-v1:0[1m]239/model opus[1m]

95```240/model sonnet[1m]

96 241 

97Note: Extended context models have242# Or append [1m] to a full model name

98[different pricing](https://docs.claude.com/en/docs/about-claude/pricing#long-context-pricing).243/model claude-opus-4-7[1m]

244```

99 245 

100## Checking your current model246## Checking your current model

101 247 


1041. In [status line](/en/statusline) (if configured)2501. In [status line](/en/statusline) (if configured)

1052. In `/status`, which also displays your account information.2512. In `/status`, which also displays your account information.

106 252 

253## Add a custom model option

254 

255Use `ANTHROPIC_CUSTOM_MODEL_OPTION` to add a single custom entry to the `/model` picker without replacing the built-in aliases. This is useful for LLM gateway deployments or testing model IDs that Claude Code does not list by default.

256 

257This example sets all three variables to make a gateway-routed Opus deployment selectable:

258 

259```bash theme={null}

260export ANTHROPIC_CUSTOM_MODEL_OPTION="my-gateway/claude-opus-4-7"

261export ANTHROPIC_CUSTOM_MODEL_OPTION_NAME="Opus via Gateway"

262export ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION="Custom deployment routed through the internal LLM gateway"

263```

264 

265The custom entry appears at the bottom of the `/model` picker. `ANTHROPIC_CUSTOM_MODEL_OPTION_NAME` and `ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION` are optional. If omitted, the model ID is used as the name and the description defaults to `Custom model (<model-id>)`.

266 

267Claude Code skips validation for the model ID set in `ANTHROPIC_CUSTOM_MODEL_OPTION`, so you can use any string your API endpoint accepts.

268 

107## Environment variables269## Environment variables

108 270 

109You can use the following environment variables, which must be full **model271You can use the following environment variables, which must be full **model


119Note: `ANTHROPIC_SMALL_FAST_MODEL` is deprecated in favor of281Note: `ANTHROPIC_SMALL_FAST_MODEL` is deprecated in favor of

120`ANTHROPIC_DEFAULT_HAIKU_MODEL`.282`ANTHROPIC_DEFAULT_HAIKU_MODEL`.

121 283 

284### Pin models for third-party deployments

285 

286When deploying Claude Code through [Bedrock](/en/amazon-bedrock), [Vertex AI](/en/google-vertex-ai), or [Foundry](/en/microsoft-foundry), pin model versions before rolling out to users.

287 

288Without pinning, Claude Code uses model aliases (`sonnet`, `opus`, `haiku`) that resolve to the latest version. When Anthropic releases a new model that isn't yet enabled in a user's account, Bedrock and Vertex AI users see a notice and fall back to the previous version for that session, while Foundry users see errors because Foundry has no equivalent startup check.

289 

290<Warning>

291 Set all three model environment variables to specific version IDs as part of your initial setup. Pinning lets you control when your users move to a new model.

292</Warning>

293 

294Use the following environment variables with version-specific model IDs for your provider:

295 

296| Provider | Example |

297| :-------- | :------------------------------------------------------------------- |

298| Bedrock | `export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-7'` |

299| Vertex AI | `export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7'` |

300| Foundry | `export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7'` |

301 

302Apply the same pattern for `ANTHROPIC_DEFAULT_SONNET_MODEL` and `ANTHROPIC_DEFAULT_HAIKU_MODEL`. For current and legacy model IDs across all providers, see [Models overview](https://platform.claude.com/docs/en/about-claude/models/overview). To upgrade users to a new model version, update these environment variables and redeploy.

303 

304To enable [extended context](#extended-context) for a pinned model, append `[1m]` to the model ID in `ANTHROPIC_DEFAULT_OPUS_MODEL` or `ANTHROPIC_DEFAULT_SONNET_MODEL`:

305 

306```bash theme={null}

307export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-7[1m]'

308```

309 

310The `[1m]` suffix applies the 1M context window to all usage of that alias, including `opusplan`. Claude Code strips the suffix before sending the model ID to your provider. Only append `[1m]` when the underlying model supports 1M context, such as Opus 4.7 or Sonnet 4.6.

311 

312<Note>

313 The `settings.availableModels` allowlist still applies when using third-party providers. Filtering matches on the model alias (`opus`, `sonnet`, `haiku`), not the provider-specific model ID.

314</Note>

315 

316### Customize pinned model display and capabilities

317 

318When you pin a model on a third-party provider, the provider-specific ID appears as-is in the `/model` picker and Claude Code may not recognize which features the model supports. You can override the display name and declare capabilities with companion environment variables for each pinned model.

319 

320These variables take effect on third-party providers such as Bedrock, Vertex AI, and Foundry. The `_NAME` and `_DESCRIPTION` variables also take effect when `ANTHROPIC_BASE_URL` points to an [LLM gateway](/en/llm-gateway). They have no effect when connecting directly to `api.anthropic.com`.

321 

322| Environment variable | Description |

323| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |

324| `ANTHROPIC_DEFAULT_OPUS_MODEL_NAME` | Display name for the pinned Opus model in the `/model` picker. Defaults to the model ID when not set |

325| `ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION` | Display description for the pinned Opus model in the `/model` picker. Defaults to `Custom Opus model` when not set |

326| `ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES` | Comma-separated list of capabilities the pinned Opus model supports |

327 

328The same `_NAME`, `_DESCRIPTION`, and `_SUPPORTED_CAPABILITIES` suffixes are available for `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL`, and `ANTHROPIC_CUSTOM_MODEL_OPTION`.

329 

330Claude Code enables features like [effort levels](#adjust-effort-level) and [extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) by matching the model ID against known patterns. Provider-specific IDs such as Bedrock ARNs or custom deployment names often don't match these patterns, leaving supported features disabled. Set `_SUPPORTED_CAPABILITIES` to tell Claude Code which features the model actually supports:

331 

332| Capability value | Enables |

333| ---------------------- | ------------------------------------------------------------------------------- |

334| `effort` | [Effort levels](#adjust-effort-level) and the `/effort` command |

335| `xhigh_effort` | {/* min-version: 2.1.111 */}The `xhigh` effort level |

336| `max_effort` | The `max` effort level |

337| `thinking` | [Extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) |

338| `adaptive_thinking` | Adaptive reasoning that dynamically allocates thinking based on task complexity |

339| `interleaved_thinking` | Thinking between tool calls |

340 

341When `_SUPPORTED_CAPABILITIES` is set, listed capabilities are enabled and unlisted capabilities are disabled for the matching pinned model. When the variable is unset, Claude Code falls back to built-in detection based on the model ID.

342 

343This example pins Opus to a Bedrock custom model ARN, sets a friendly name, and declares its capabilities:

344 

345```bash theme={null}

346export ANTHROPIC_DEFAULT_OPUS_MODEL='arn:aws:bedrock:us-east-1:123456789012:custom-model/abc'

347export ANTHROPIC_DEFAULT_OPUS_MODEL_NAME='Opus via Bedrock'

348export ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION='Opus 4.7 routed through a Bedrock custom endpoint'

349export ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES='effort,xhigh_effort,max_effort,thinking,adaptive_thinking,interleaved_thinking'

350```

351 

352### Override model IDs per version

353 

354The family-level environment variables above configure one model ID per family alias. If you need to map several versions within the same family to distinct provider IDs, use the `modelOverrides` setting instead.

355 

356`modelOverrides` maps individual Anthropic model IDs to the provider-specific strings that Claude Code sends to your provider's API. When a user selects a mapped model in the `/model` picker, Claude Code uses your configured value instead of the built-in default.

357 

358This lets enterprise administrators route each model version to a specific Bedrock inference profile ARN, Vertex AI version name, or Foundry deployment name for governance, cost allocation, or regional routing.

359 

360Set `modelOverrides` in your [settings file](/en/settings#settings-files):

361 

362```json theme={null}

363{

364 "modelOverrides": {

365 "claude-opus-4-7": "arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-prod",

366 "claude-opus-4-6": "arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/opus-46-prod",

367 "claude-sonnet-4-6": "arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/sonnet-prod"

368 }

369}

370```

371 

372Keys must be Anthropic model IDs as listed in the [Models overview](https://platform.claude.com/docs/en/about-claude/models/overview). For dated model IDs, include the date suffix exactly as it appears there. Unknown keys are ignored.

373 

374Overrides replace the built-in model IDs that back each entry in the `/model` picker. On Bedrock, overrides take precedence over any inference profiles that Claude Code discovers automatically at startup. Values you supply directly through `ANTHROPIC_MODEL`, `--model`, or the `ANTHROPIC_DEFAULT_*_MODEL` environment variables are passed to the provider as-is and are not transformed by `modelOverrides`.

375 

376`modelOverrides` works alongside `availableModels`. The allowlist is evaluated against the Anthropic model ID, not the override value, so an entry like `"opus"` in `availableModels` continues to match even when Opus versions are mapped to ARNs.

377 

122### Prompt caching configuration378### Prompt caching configuration

123 379 

124Claude Code automatically uses [prompt caching](https://docs.claude.com/en/docs/build-with-claude/prompt-caching) to optimize performance and reduce costs. You can disable prompt caching globally or for specific model tiers:380Claude Code automatically uses [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) to optimize performance and reduce costs. You can disable prompt caching globally or for specific model tiers:

125 381 

126| Environment variable | Description |382| Environment variable | Description |

127| ------------------------------- | ---------------------------------------------------------------------------------------------- |383| ------------------------------- | ---------------------------------------------------------------------------------------------- |

monitoring-usage.md +478 −47

Details

6 6 

7> Learn how to enable and configure OpenTelemetry for Claude Code.7> Learn how to enable and configure OpenTelemetry for Claude Code.

8 8 

9Claude Code supports OpenTelemetry (OTel) metrics and events for monitoring and observability.9Track Claude Code usage, costs, and tool activity across your organization by exporting telemetry data through OpenTelemetry (OTel). Claude Code exports metrics as time series data via the standard metrics protocol, events via the logs/events protocol, and optionally distributed traces via the [traces protocol](#traces-beta). Configure your metrics, logs, and traces backends to match your monitoring requirements.

10 

11All metrics are time series data exported via OpenTelemetry's standard metrics protocol, and events are exported via OpenTelemetry's logs/events protocol. It is the user's responsibility to ensure their metrics and logs backends are properly configured and that the aggregation granularity meets their monitoring requirements.

12 10 

13## Quick start11## Quick start

14 12 


19export CLAUDE_CODE_ENABLE_TELEMETRY=117export CLAUDE_CODE_ENABLE_TELEMETRY=1

20 18 

21# 2. Choose exporters (both are optional - configure only what you need)19# 2. Choose exporters (both are optional - configure only what you need)

22export OTEL_METRICS_EXPORTER=otlp # Options: otlp, prometheus, console20export OTEL_METRICS_EXPORTER=otlp # Options: otlp, prometheus, console, none

23export OTEL_LOGS_EXPORTER=otlp # Options: otlp, console21export OTEL_LOGS_EXPORTER=otlp # Options: otlp, console, none

24 22 

25# 3. Configure OTLP endpoint (for OTLP exporter)23# 3. Configure OTLP endpoint (for OTLP exporter)

26export OTEL_EXPORTER_OTLP_PROTOCOL=grpc24export OTEL_EXPORTER_OTLP_PROTOCOL=grpc


56 "OTEL_METRICS_EXPORTER": "otlp",54 "OTEL_METRICS_EXPORTER": "otlp",

57 "OTEL_LOGS_EXPORTER": "otlp",55 "OTEL_LOGS_EXPORTER": "otlp",

58 "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",56 "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",

59 "OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.company.com:4317",57 "OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4317",

60 "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer company-token"58 "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer example-token"

61 }59 }

62}60}

63```61```


71### Common configuration variables69### Common configuration variables

72 70 

73| Environment Variable | Description | Example Values |71| Environment Variable | Description | Example Values |

74| ----------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------ |72| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |

75| `CLAUDE_CODE_ENABLE_TELEMETRY` | Enables telemetry collection (required) | `1` |73| `CLAUDE_CODE_ENABLE_TELEMETRY` | Enables telemetry collection (required) | `1` |

76| `OTEL_METRICS_EXPORTER` | Metrics exporter type(s) (comma-separated) | `console`, `otlp`, `prometheus` |74| `OTEL_METRICS_EXPORTER` | Metrics exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `prometheus`, `none` |

77| `OTEL_LOGS_EXPORTER` | Logs/events exporter type(s) (comma-separated) | `console`, `otlp` |75| `OTEL_LOGS_EXPORTER` | Logs/events exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `none` |

78| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol for OTLP exporter (all signals) | `grpc`, `http/json`, `http/protobuf` |76| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol for OTLP exporter, applies to all signals | `grpc`, `http/json`, `http/protobuf` |

79| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint (all signals) | `http://localhost:4317` |77| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint for all signals | `http://localhost:4317` |

80| `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | Protocol for metrics (overrides general) | `grpc`, `http/json`, `http/protobuf` |78| `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | Protocol for metrics, overrides general setting | `grpc`, `http/json`, `http/protobuf` |

81| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | OTLP metrics endpoint (overrides general) | `http://localhost:4318/v1/metrics` |79| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | OTLP metrics endpoint, overrides general setting | `http://localhost:4318/v1/metrics` |

82| `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` | Protocol for logs (overrides general) | `grpc`, `http/json`, `http/protobuf` |80| `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` | Protocol for logs, overrides general setting | `grpc`, `http/json`, `http/protobuf` |

83| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | OTLP logs endpoint (overrides general) | `http://localhost:4318/v1/logs` |81| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | OTLP logs endpoint, overrides general setting | `http://localhost:4318/v1/logs` |

84| `OTEL_EXPORTER_OTLP_HEADERS` | Authentication headers for OTLP | `Authorization=Bearer token` |82| `OTEL_EXPORTER_OTLP_HEADERS` | Authentication headers for OTLP | `Authorization=Bearer token` |

85| `OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY` | Client key for mTLS authentication | Path to client key file |83| `OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY` | Client key for mTLS authentication | Path to client key file |

86| `OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE` | Client certificate for mTLS authentication | Path to client cert file |84| `OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE` | Client certificate for mTLS authentication | Path to client cert file |

87| `OTEL_METRIC_EXPORT_INTERVAL` | Export interval in milliseconds (default: 60000) | `5000`, `60000` |85| `OTEL_METRIC_EXPORT_INTERVAL` | Export interval in milliseconds (default: 60000) | `5000`, `60000` |

88| `OTEL_LOGS_EXPORT_INTERVAL` | Logs export interval in milliseconds (default: 5000) | `1000`, `10000` |86| `OTEL_LOGS_EXPORT_INTERVAL` | Logs export interval in milliseconds (default: 5000) | `1000`, `10000` |

89| `OTEL_LOG_USER_PROMPTS` | Enable logging of user prompt content (default: disabled) | `1` to enable |87| `OTEL_LOG_USER_PROMPTS` | Enable logging of user prompt content (default: disabled) | `1` to enable |

88| `OTEL_LOG_TOOL_DETAILS` | Enable logging of tool parameters and input arguments in tool events and trace span attributes: Bash commands, MCP server and tool names, skill names, and tool input. Also enables custom, plugin, and MCP command names on `user_prompt` events (default: disabled) | `1` to enable |

89| `OTEL_LOG_TOOL_CONTENT` | Enable logging of tool input and output content in span events (default: disabled). Requires [tracing](#traces-beta). Content is truncated at 60 KB | `1` to enable |

90| `OTEL_LOG_RAW_API_BODIES` | Emit the full Anthropic Messages API request and response JSON as `api_request_body` / `api_response_body` log events (default: disabled). Bodies include the entire conversation history. Enabling this implies consent to everything `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_TOOL_DETAILS`, and `OTEL_LOG_TOOL_CONTENT` would reveal | `1` for inline bodies truncated at 60 KB, or `file:<dir>` for untruncated bodies on disk with a `body_ref` pointer in the event |

91| `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | Metrics temporality preference (default: `delta`). Set to `cumulative` if your backend expects cumulative temporality | `delta`, `cumulative` |

90| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic headers (default: 1740000ms / 29 minutes) | `900000` |92| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic headers (default: 1740000ms / 29 minutes) | `900000` |

91 93 

92### Metrics cardinality control94### Metrics cardinality control


94The following environment variables control which attributes are included in metrics to manage cardinality:96The following environment variables control which attributes are included in metrics to manage cardinality:

95 97 

96| Environment Variable | Description | Default Value | Example to Disable |98| Environment Variable | Description | Default Value | Example to Disable |

97| ----------------------------------- | ----------------------------------------------- | ------------- | ------------------ |99| ----------------------------------- | --------------------------------------------------------------------- | ------------- | ------------------ |

98| `OTEL_METRICS_INCLUDE_SESSION_ID` | Include session.id attribute in metrics | `true` | `false` |100| `OTEL_METRICS_INCLUDE_SESSION_ID` | Include session.id attribute in metrics | `true` | `false` |

99| `OTEL_METRICS_INCLUDE_VERSION` | Include app.version attribute in metrics | `false` | `true` |101| `OTEL_METRICS_INCLUDE_VERSION` | Include app.version attribute in metrics | `false` | `true` |

100| `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` | Include user.account\_uuid attribute in metrics | `true` | `false` |102| `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` | Include user.account\_uuid and user.account\_id attributes in metrics | `true` | `false` |

101 103 

102These variables help control the cardinality of metrics, which affects storage requirements and query performance in your metrics backend. Lower cardinality generally means better performance and lower storage costs but less granular data for analysis.104These variables help control the cardinality of metrics, which affects storage requirements and query performance in your metrics backend. Lower cardinality generally means better performance and lower storage costs but less granular data for analysis.

103 105 

106### Traces (beta)

107 

108Distributed tracing exports spans that link each user prompt to the API requests and tool executions it triggers, so you can view a full request as a single trace in your tracing backend.

109 

110Tracing is off by default. To enable it, set both `CLAUDE_CODE_ENABLE_TELEMETRY=1` and `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1`, then set `OTEL_TRACES_EXPORTER` to choose where spans are sent. Traces reuse the [common OTLP configuration](#common-configuration-variables) for endpoint, protocol, and headers.

111 

112| Environment Variable | Description | Example Values |

113| ------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------ |

114| `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` | Enable span tracing (required). `ENABLE_ENHANCED_TELEMETRY_BETA` is also accepted | `1` |

115| `OTEL_TRACES_EXPORTER` | Traces exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `none` |

116| `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` | Protocol for traces, overrides `OTEL_EXPORTER_OTLP_PROTOCOL` | `grpc`, `http/json`, `http/protobuf` |

117| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | OTLP traces endpoint, overrides `OTEL_EXPORTER_OTLP_ENDPOINT` | `http://localhost:4318/v1/traces` |

118| `OTEL_TRACES_EXPORT_INTERVAL` | Span batch export interval in milliseconds (default: 5000) | `1000`, `10000` |

119 

120Spans redact user prompt text, tool input details, and tool content by default. Set `OTEL_LOG_USER_PROMPTS=1`, `OTEL_LOG_TOOL_DETAILS=1`, and `OTEL_LOG_TOOL_CONTENT=1` to include them.

121 

122When tracing is active, Bash and PowerShell subprocesses automatically inherit a `TRACEPARENT` environment variable containing the W3C trace context of the active tool execution span. This lets any subprocess that reads `TRACEPARENT` parent its own spans under the same trace, enabling end-to-end distributed tracing through scripts and commands that Claude runs.

123 

124In Agent SDK and non-interactive sessions started with `-p`, Claude Code also reads `TRACEPARENT` and `TRACESTATE` from its own environment when starting each interaction span. This lets an embedding process pass its active W3C trace context into the subprocess so Claude Code's spans appear as children of the caller's distributed trace. Interactive sessions ignore inbound `TRACEPARENT` to avoid accidentally inheriting ambient values from CI or container environments.

125 

126#### Span hierarchy

127 

128Each user prompt starts a `claude_code.interaction` root span. API calls, tool calls, and hook executions are recorded as its children. Tool spans have two child spans of their own: one for the time spent waiting on a permission decision and one for the execution itself. When the Task tool spawns a subagent, the subagent's API and tool spans nest under the parent's `claude_code.tool` span.

129 

130```text theme={null}

131claude_code.interaction

132├── claude_code.llm_request

133├── claude_code.hook (requires detailed beta tracing)

134└── claude_code.tool

135 ├── claude_code.tool.blocked_on_user

136 ├── claude_code.tool.execution

137 └── (Task tool) subagent claude_code.llm_request / claude_code.tool spans

138```

139 

140In Agent SDK and `claude -p` sessions, `claude_code.interaction` itself becomes a child of the caller's span when `TRACEPARENT` is set in the environment.

141 

142#### Span attributes

143 

144Every span carries the [standard attributes](#standard-attributes) plus a `span.type` attribute matching its name. The tables below list the additional attributes set on each span. The `llm_request`, `tool.execution`, and `hook` spans set OpenTelemetry status `ERROR` when they record a failure; the other spans always end with status `UNSET`.

145 

146**`claude_code.interaction`**

147 

148| Attribute | Description | Gated by |

149| ------------------------- | --------------------------------------------------------- | ----------------------- |

150| `user_prompt` | Prompt text. Value is `<REDACTED>` unless the gate is set | `OTEL_LOG_USER_PROMPTS` |

151| `user_prompt_length` | Prompt length in characters | |

152| `interaction.sequence` | 1-based counter of interactions in this session | |

153| `interaction.duration_ms` | Wall-clock duration of the turn | |

154 

155**`claude_code.llm_request`**

156 

157| Attribute | Description | Gated by |

158| ------------------------ | -------------------------------------------------------------------------------- | -------- |

159| `model` | Model identifier | |

160| `gen_ai.system` | Always `anthropic`. OpenTelemetry GenAI semantic convention | |

161| `gen_ai.request.model` | Same value as `model`. OpenTelemetry GenAI semantic convention | |

162| `query_source` | Subsystem that issued the request, such as `repl_main_thread` or a subagent name | |

163| `speed` | `fast` or `normal` | |

164| `llm_request.context` | `interaction`, `tool`, or `standalone` depending on the parent span | |

165| `duration_ms` | Wall-clock duration including retries | |

166| `ttft_ms` | Time to first token in milliseconds | |

167| `input_tokens` | Input token count from the API usage block | |

168| `output_tokens` | Output token count | |

169| `cache_read_tokens` | Tokens read from prompt cache | |

170| `cache_creation_tokens` | Tokens written to prompt cache | |

171| `request_id` | Anthropic API request ID from the `request-id` response header | |

172| `gen_ai.response.id` | Same value as `request_id`. OpenTelemetry GenAI semantic convention | |

173| `client_request_id` | Client-generated `x-client-request-id` of the final attempt | |

174| `attempt` | Total attempts made for this request | |

175| `success` | `true` or `false` | |

176| `status_code` | HTTP status code when the request failed | |

177| `error` | Error message when the request failed | |

178| `response.has_tool_call` | `true` when the response contained tool-use blocks | |

179 

180Each retry attempt is also recorded as a `gen_ai.request.attempt` span event with `attempt` and `client_request_id` attributes.

181 

182**`claude_code.tool`**

183 

184| Attribute | Description | Gated by |

185| --------------- | ----------------------------------------------------------- | ----------------------- |

186| `tool_name` | Tool name | |

187| `duration_ms` | Wall-clock duration including permission wait and execution | |

188| `result_tokens` | Approximate token size of the tool result | |

189| `file_path` | Target file path for Read, Edit, and Write tools | `OTEL_LOG_TOOL_DETAILS` |

190| `full_command` | Command string for the Bash tool | `OTEL_LOG_TOOL_DETAILS` |

191| `skill_name` | Skill name for the Skill tool | `OTEL_LOG_TOOL_DETAILS` |

192| `subagent_type` | Subagent type for the Task tool | `OTEL_LOG_TOOL_DETAILS` |

193 

194When `OTEL_LOG_TOOL_CONTENT=1`, this span also records a `tool.output` span event whose attributes contain the tool's input and output bodies, truncated at 60 KB per attribute.

195 

196**`claude_code.tool.blocked_on_user`**

197 

198| Attribute | Description | Gated by |

199| ------------- | --------------------------------------------------- | -------- |

200| `duration_ms` | Time spent waiting for the permission decision | |

201| `decision` | `accept` or `reject` | |

202| `source` | Decision source, matching the `tool_decision` event | |

203 

204**`claude_code.tool.execution`**

205 

206| Attribute | Description | Gated by |

207| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |

208| `duration_ms` | Time spent running the tool body | |

209| `success` | `true` or `false` | |

210| `error` | Error category string when execution failed, such as `Error:ENOENT` or `ShellError`. Contains the full error message instead when the gate is set | `OTEL_LOG_TOOL_DETAILS` |

211 

212**`claude_code.hook`**

213 

214This span is emitted only when detailed beta tracing is active, which requires `ENABLE_BETA_TRACING_DETAILED=1` and `BETA_TRACING_ENDPOINT` in addition to the trace exporter configuration above. In interactive CLI sessions, this also requires your organization to be allowlisted for the feature. Agent SDK and non-interactive `-p` sessions are not gated. It is not emitted when only `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` is set.

215 

216| Attribute | Description | Gated by |

217| ------------------------ | ------------------------------------------------ | ----------------------- |

218| `hook_event` | Hook event type, such as `PreToolUse` | |

219| `hook_name` | Full hook name, such as `PreToolUse:Write` | |

220| `num_hooks` | Number of matching hook commands executed | |

221| `hook_definitions` | JSON-serialized hook configuration | `OTEL_LOG_TOOL_DETAILS` |

222| `duration_ms` | Wall-clock duration of all matching hooks | |

223| `num_success` | Count of hooks that completed successfully | |

224| `num_blocking` | Count of hooks that returned a blocking decision | |

225| `num_non_blocking_error` | Count of hooks that failed without blocking | |

226| `num_cancelled` | Count of hooks cancelled before completion | |

227 

228<Note>

229 Additional content-bearing attributes such as `new_context`, `system_prompt_preview`, `tool_input`, and `response.model_output` are emitted only when detailed beta tracing is active. They are not part of the stable span schema.

230</Note>

231 

104### Dynamic headers232### Dynamic headers

105 233 

106For enterprise environments that require dynamic authentication, you can configure a script to generate headers dynamically:234For enterprise environments that require dynamic authentication, you can configure a script to generate headers dynamically:


148<Warning>276<Warning>

149 **Important formatting requirements for OTEL\_RESOURCE\_ATTRIBUTES:**277 **Important formatting requirements for OTEL\_RESOURCE\_ATTRIBUTES:**

150 278 

151 The `OTEL_RESOURCE_ATTRIBUTES` environment variable follows the [W3C Baggage specification](https://www.w3.org/TR/baggage/), which has strict formatting requirements:279 The `OTEL_RESOURCE_ATTRIBUTES` environment variable uses comma-separated key=value pairs with strict formatting requirements:

152 280 

153 * **No spaces allowed**: Values cannot contain spaces. For example, `user.organizationName=My Company` is invalid281 * **No spaces allowed**: Values cannot contain spaces. For example, `user.organizationName=My Company` is invalid

154 * **Format**: Must be comma-separated key=value pairs: `key1=value1,key2=value2`282 * **Format**: Must be comma-separated key=value pairs: `key1=value1,key2=value2`


174 302 

175### Example configurations303### Example configurations

176 304 

305Set these environment variables before running `claude`. Each block shows a complete configuration for a different exporter or deployment scenario:

306 

177```bash theme={null}307```bash theme={null}

178# Console debugging (1-second intervals)308# Console debugging (1-second intervals)

179export CLAUDE_CODE_ENABLE_TELEMETRY=1309export CLAUDE_CODE_ENABLE_TELEMETRY=1


200export OTEL_METRICS_EXPORTER=otlp330export OTEL_METRICS_EXPORTER=otlp

201export OTEL_LOGS_EXPORTER=otlp331export OTEL_LOGS_EXPORTER=otlp

202export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf332export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf

203export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://metrics.company.com:4318333export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://metrics.example.com:4318

204export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=grpc334export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=grpc

205export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://logs.company.com:4317335export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://logs.example.com:4317

206 336 

207# Metrics only (no events/logs)337# Metrics only (no events/logs)

208export CLAUDE_CODE_ENABLE_TELEMETRY=1338export CLAUDE_CODE_ENABLE_TELEMETRY=1


224All metrics and events share these standard attributes:354All metrics and events share these standard attributes:

225 355 

226| Attribute | Description | Controlled By |356| Attribute | Description | Controlled By |

227| ------------------- | -------------------------------------------------------------------- | --------------------------------------------------- |357| ------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |

228| `session.id` | Unique session identifier | `OTEL_METRICS_INCLUDE_SESSION_ID` (default: true) |358| `session.id` | Unique session identifier | `OTEL_METRICS_INCLUDE_SESSION_ID` (default: true) |

229| `app.version` | Current Claude Code version | `OTEL_METRICS_INCLUDE_VERSION` (default: false) |359| `app.version` | Current Claude Code version | `OTEL_METRICS_INCLUDE_VERSION` (default: false) |

230| `organization.id` | Organization UUID (when authenticated) | Always included when available |360| `organization.id` | Organization UUID (when authenticated) | Always included when available |

231| `user.account_uuid` | Account UUID (when authenticated) | `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` (default: true) |361| `user.account_uuid` | Account UUID (when authenticated) | `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` (default: true) |

232| `terminal.type` | Terminal type (for example, `iTerm.app`, `vscode`, `cursor`, `tmux`) | Always included when detected |362| `user.account_id` | Account ID in tagged format matching Anthropic admin APIs (when authenticated), such as `user_01BWBeN28...` | `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` (default: true) |

363| `user.id` | Anonymous device/installation identifier, generated per Claude Code installation | Always included |

364| `user.email` | User email address (when authenticated via OAuth) | Always included when available |

365| `terminal.type` | Terminal type, such as `iTerm.app`, `vscode`, `cursor`, or `tmux` | Always included when detected |

366 

367Events additionally include the following attributes. These are never attached to metrics because they would cause unbounded cardinality:

368 

369* `prompt.id`: UUID correlating a user prompt with all subsequent events until the next prompt. See [Event correlation attributes](#event-correlation-attributes).

370* `workspace.host_paths`: host workspace directories selected in the desktop app, as a string array

233 371 

234### Metrics372### Metrics

235 373 


248 386 

249### Metric details387### Metric details

250 388 

389Each metric includes the standard attributes listed above. Metrics with additional context-specific attributes are noted below.

390 

251#### Session counter391#### Session counter

252 392 

253Incremented at the start of each session.393Incremented at the start of each session.


255**Attributes**:395**Attributes**:

256 396 

257* All [standard attributes](#standard-attributes)397* All [standard attributes](#standard-attributes)

398* `start_type`: How the session was started. One of `"fresh"`, `"resume"`, or `"continue"`

258 399 

259#### Lines of code counter400#### Lines of code counter

260 401 


288**Attributes**:429**Attributes**:

289 430 

290* All [standard attributes](#standard-attributes)431* All [standard attributes](#standard-attributes)

291* `model`: Model identifier (for example, "claude-sonnet-4-5-20250929")432* `model`: Model identifier (for example, "claude-sonnet-4-6")

433* `query_source`: Category of the subsystem that issued the request. One of `"main"`, `"subagent"`, or `"auxiliary"`

434* `speed`: `"fast"` when the request used fast mode. Absent otherwise

435* `effort`: [Effort level](/en/model-config#adjust-effort-level) applied to the request: `"low"`, `"medium"`, `"high"`, `"xhigh"`, or `"max"`. Absent when the model does not support effort.

292 436 

293#### Token counter437#### Token counter

294 438 


298 442 

299* All [standard attributes](#standard-attributes)443* All [standard attributes](#standard-attributes)

300* `type`: (`"input"`, `"output"`, `"cacheRead"`, `"cacheCreation"`)444* `type`: (`"input"`, `"output"`, `"cacheRead"`, `"cacheCreation"`)

301* `model`: Model identifier (for example, "claude-sonnet-4-5-20250929")445* `model`: Model identifier (for example, "claude-sonnet-4-6")

446* `query_source`: Category of the subsystem that issued the request. One of `"main"`, `"subagent"`, or `"auxiliary"`

447* `speed`: `"fast"` when the request used fast mode. Absent otherwise

448* `effort`: [Effort level](/en/model-config#adjust-effort-level) applied to the request. See [Cost counter](#cost-counter) for details.

302 449 

303#### Code edit tool decision counter450#### Code edit tool decision counter

304 451 


307**Attributes**:454**Attributes**:

308 455 

309* All [standard attributes](#standard-attributes)456* All [standard attributes](#standard-attributes)

310* `tool`: Tool name (`"Edit"`, `"Write"`, `"NotebookEdit"`)457* `tool_name`: Tool name (`"Edit"`, `"Write"`, `"NotebookEdit"`)

311* `decision`: User decision (`"accept"`, `"reject"`)458* `decision`: User decision (`"accept"`, `"reject"`)

312* `language`: Programming language of the edited file (for example, `"TypeScript"`, `"Python"`, `"JavaScript"`, `"Markdown"`). Returns `"unknown"` for unrecognized file extensions.459* `source`: Decision source - `"config"`, `"hook"`, `"user_permanent"`, `"user_temporary"`, `"user_abort"`, or `"user_reject"`

460* `language`: Programming language of the edited file, such as `"TypeScript"`, `"Python"`, `"JavaScript"`, or `"Markdown"`. Returns `"unknown"` for unrecognized file extensions.

313 461 

314#### Active time counter462#### Active time counter

315 463 

316Tracks actual time spent actively using Claude Code (not idle time). This metric is incremented during user interactions such as typing prompts or receiving responses.464Tracks actual time spent actively using Claude Code, excluding idle time. This metric is incremented during user interactions (typing, reading responses) and during CLI processing (tool execution, AI response generation).

317 465 

318**Attributes**:466**Attributes**:

319 467 

320* All [standard attributes](#standard-attributes)468* All [standard attributes](#standard-attributes)

469* `type`: `"user"` for keyboard interactions, `"cli"` for tool execution and AI responses

321 470 

322### Events471### Events

323 472 

324Claude Code exports the following events via OpenTelemetry logs/events (when `OTEL_LOGS_EXPORTER` is configured):473Claude Code exports the following events via OpenTelemetry logs/events (when `OTEL_LOGS_EXPORTER` is configured):

325 474 

475#### Event correlation attributes

476 

477When a user submits a prompt, Claude Code may make multiple API calls and run several tools. The `prompt.id` attribute lets you tie all of those events back to the single prompt that triggered them.

478 

479| Attribute | Description |

480| ----------- | ------------------------------------------------------------------------------------ |

481| `prompt.id` | UUID v4 identifier linking all events produced while processing a single user prompt |

482 

483To trace all activity triggered by a single prompt, filter your events by a specific `prompt.id` value. This returns the user\_prompt event, any api\_request events, and any tool\_result events that occurred while processing that prompt.

484 

485<Note>

486 `prompt.id` is intentionally excluded from metrics because each prompt generates a unique ID, which would create an ever-growing number of time series. Use it for event-level analysis and audit trails only.

487</Note>

488 

326#### User prompt event489#### User prompt event

327 490 

328Logged when a user submits a prompt.491Logged when a user submits a prompt.


334* All [standard attributes](#standard-attributes)497* All [standard attributes](#standard-attributes)

335* `event.name`: `"user_prompt"`498* `event.name`: `"user_prompt"`

336* `event.timestamp`: ISO 8601 timestamp499* `event.timestamp`: ISO 8601 timestamp

500* `event.sequence`: monotonically increasing counter for ordering events within a session

337* `prompt_length`: Length of the prompt501* `prompt_length`: Length of the prompt

338* `prompt`: Prompt content (redacted by default, enable with `OTEL_LOG_USER_PROMPTS=1`)502* `prompt`: Prompt content (redacted by default, enable with `OTEL_LOG_USER_PROMPTS=1`)

503* `command_name`: Command name when the prompt invokes one. Built-in and bundled command names such as `compact` or `debug` are emitted as-is; aliases such as `reset` emit as typed rather than the canonical name. Custom, plugin, and MCP command names collapse to `custom` or `mcp` unless `OTEL_LOG_TOOL_DETAILS=1` is set

504* `command_source`: Origin of the command when present: `builtin`, `custom`, or `mcp`. Plugin-provided commands report as `custom`

339 505 

340#### Tool result event506#### Tool result event

341 507 


348* All [standard attributes](#standard-attributes)514* All [standard attributes](#standard-attributes)

349* `event.name`: `"tool_result"`515* `event.name`: `"tool_result"`

350* `event.timestamp`: ISO 8601 timestamp516* `event.timestamp`: ISO 8601 timestamp

517* `event.sequence`: monotonically increasing counter for ordering events within a session

351* `tool_name`: Name of the tool518* `tool_name`: Name of the tool

519* `tool_use_id`: Unique identifier for this tool invocation. Matches the `tool_use_id` passed to hooks, allowing correlation between OTel events and hook-captured data.

352* `success`: `"true"` or `"false"`520* `success`: `"true"` or `"false"`

353* `duration_ms`: Execution time in milliseconds521* `duration_ms`: Execution time in milliseconds

354* `error`: Error message (if failed)522* `error_type`: Error category string when the tool failed, such as `"Error:ENOENT"` or `"ShellError"`

355* `decision`: Either `"accept"` or `"reject"`523* `error` (when `OTEL_LOG_TOOL_DETAILS=1`): Full error message when the tool failed

356* `source`: Decision source - `"config"`, `"user_permanent"`, `"user_temporary"`, `"user_abort"`, or `"user_reject"`524* `decision_type`: Either `"accept"` or `"reject"`

357* `tool_parameters`: JSON string containing tool-specific parameters (when available)525* `decision_source`: Decision source - `"config"`, `"hook"`, `"user_permanent"`, `"user_temporary"`, `"user_abort"`, or `"user_reject"`

358 * For Bash tool: includes `bash_command`, `full_command`, `timeout`, `description`, `sandbox`526* `tool_input_size_bytes`: Size of the JSON-serialized tool input in bytes

527* `tool_result_size_bytes`: Size of the tool result in bytes

528* `mcp_server_scope`: MCP server scope identifier (for MCP tools)

529* `tool_parameters` (when `OTEL_LOG_TOOL_DETAILS=1`): JSON string containing tool-specific parameters:

530 * For Bash tool: includes `bash_command`, `full_command`, `timeout`, `description`, `dangerouslyDisableSandbox`, and `git_commit_id` (the commit SHA, when a `git commit` command succeeds)

531 * For MCP tools: includes `mcp_server_name`, `mcp_tool_name`

532 * For Skill tool: includes `skill_name`

533 * For Task tool: includes `subagent_type`

534* `tool_input` (when `OTEL_LOG_TOOL_DETAILS=1`): JSON-serialized tool arguments. Individual values over 512 characters are truncated, and the full payload is bounded to \~4 K characters. Applies to all tools including MCP tools.

359 535 

360#### API request event536#### API request event

361 537 


368* All [standard attributes](#standard-attributes)544* All [standard attributes](#standard-attributes)

369* `event.name`: `"api_request"`545* `event.name`: `"api_request"`

370* `event.timestamp`: ISO 8601 timestamp546* `event.timestamp`: ISO 8601 timestamp

371* `model`: Model used (for example, "claude-sonnet-4-5-20250929")547* `event.sequence`: monotonically increasing counter for ordering events within a session

548* `model`: Model used (for example, "claude-sonnet-4-6")

372* `cost_usd`: Estimated cost in USD549* `cost_usd`: Estimated cost in USD

373* `duration_ms`: Request duration in milliseconds550* `duration_ms`: Request duration in milliseconds

374* `input_tokens`: Number of input tokens551* `input_tokens`: Number of input tokens

375* `output_tokens`: Number of output tokens552* `output_tokens`: Number of output tokens

376* `cache_read_tokens`: Number of tokens read from cache553* `cache_read_tokens`: Number of tokens read from cache

377* `cache_creation_tokens`: Number of tokens used for cache creation554* `cache_creation_tokens`: Number of tokens used for cache creation

555* `request_id`: Anthropic API request ID from the response's `request-id` header, such as `"req_011..."`. Present only when the API returns one.

556* `speed`: `"fast"` or `"normal"`, indicating whether fast mode was active

557* `query_source`: Subsystem that issued the request, such as `"repl_main_thread"`, `"compact"`, or a subagent name

558* `effort`: [Effort level](/en/model-config#adjust-effort-level) applied to the request: `"low"`, `"medium"`, `"high"`, `"xhigh"`, or `"max"`. Absent when the model does not support effort.

378 559 

379#### API error event560#### API error event

380 561 


387* All [standard attributes](#standard-attributes)568* All [standard attributes](#standard-attributes)

388* `event.name`: `"api_error"`569* `event.name`: `"api_error"`

389* `event.timestamp`: ISO 8601 timestamp570* `event.timestamp`: ISO 8601 timestamp

390* `model`: Model used (for example, "claude-sonnet-4-5-20250929")571* `event.sequence`: monotonically increasing counter for ordering events within a session

572* `model`: Model used (for example, "claude-sonnet-4-6")

391* `error`: Error message573* `error`: Error message

392* `status_code`: HTTP status code (if applicable)574* `status_code`: HTTP status code as a string, or `"undefined"` for non-HTTP errors

393* `duration_ms`: Request duration in milliseconds575* `duration_ms`: Request duration in milliseconds

394* `attempt`: Attempt number (for retried requests)576* `attempt`: Total number of attempts made, including the initial request (`1` means no retries occurred)

577* `request_id`: Anthropic API request ID from the response's `request-id` header, such as `"req_011..."`. Present only when the API returns one.

578* `speed`: `"fast"` or `"normal"`, indicating whether fast mode was active

579* `query_source`: Subsystem that issued the request, such as `"repl_main_thread"`, `"compact"`, or a subagent name

580* `effort`: [Effort level](/en/model-config#adjust-effort-level) applied to the request. Absent when the model does not support effort.

581 

582#### API request body event

583 

584Logged for each API request attempt when `OTEL_LOG_RAW_API_BODIES` is set. One event is emitted per attempt, so retries with adjusted parameters each produce their own event.

585 

586**Event Name**: `claude_code.api_request_body`

587 

588**Attributes**:

589 

590* All [standard attributes](#standard-attributes)

591* `event.name`: `"api_request_body"`

592* `event.timestamp`: ISO 8601 timestamp

593* `event.sequence`: monotonically increasing counter for ordering events within a session

594* `body`: JSON-serialized Messages API request parameters (system prompt, messages, tools, etc.), truncated at 60 KB. Extended-thinking content in prior assistant turns is redacted. Emitted only in inline mode (`OTEL_LOG_RAW_API_BODIES=1`).

595* `body_ref`: Absolute path to a `<dir>/<uuid>.request.json` file containing the untruncated body. Emitted only in file mode (`OTEL_LOG_RAW_API_BODIES=file:<dir>`).

596* `body_length`: Untruncated body length. UTF-8 bytes when `OTEL_LOG_RAW_API_BODIES=file:<dir>`, or UTF-16 code units when `=1`

597* `body_truncated`: `"true"` when inline truncation occurred. Absent in file mode and when no truncation occurred.

598* `model`: Model identifier from the request parameters

599* `query_source`: Subsystem that issued the request (for example, `"compact"`)

600 

601#### API response body event

602 

603Logged for each successful API response when `OTEL_LOG_RAW_API_BODIES` is set.

604 

605**Event Name**: `claude_code.api_response_body`

606 

607**Attributes**:

608 

609* All [standard attributes](#standard-attributes)

610* `event.name`: `"api_response_body"`

611* `event.timestamp`: ISO 8601 timestamp

612* `event.sequence`: monotonically increasing counter for ordering events within a session

613* `body`: JSON-serialized Messages API response (id, content blocks, usage, stop reason), truncated at 60 KB. Extended-thinking content is redacted. Emitted only in inline mode (`OTEL_LOG_RAW_API_BODIES=1`).

614* `body_ref`: Absolute path to a `<dir>/<request_id>.response.json` file containing the untruncated body. Emitted only in file mode (`OTEL_LOG_RAW_API_BODIES=file:<dir>`).

615* `body_length`: Untruncated body length. UTF-8 bytes when `OTEL_LOG_RAW_API_BODIES=file:<dir>`, or UTF-16 code units when `=1`

616* `body_truncated`: `"true"` when inline truncation occurred. Absent in file mode and when no truncation occurred.

617* `model`: Model identifier

618* `query_source`: Subsystem that issued the request

619* `request_id`: Anthropic API request ID from the response's `request-id` header, such as `"req_011..."`. Present only when the API returns one.

395 620 

396#### Tool decision event621#### Tool decision event

397 622 


404* All [standard attributes](#standard-attributes)629* All [standard attributes](#standard-attributes)

405* `event.name`: `"tool_decision"`630* `event.name`: `"tool_decision"`

406* `event.timestamp`: ISO 8601 timestamp631* `event.timestamp`: ISO 8601 timestamp

632* `event.sequence`: monotonically increasing counter for ordering events within a session

407* `tool_name`: Name of the tool (for example, "Read", "Edit", "Write", "NotebookEdit")633* `tool_name`: Name of the tool (for example, "Read", "Edit", "Write", "NotebookEdit")

634* `tool_use_id`: Unique identifier for this tool invocation. Matches the `tool_use_id` passed to hooks, allowing correlation between OTel events and hook-captured data.

408* `decision`: Either `"accept"` or `"reject"`635* `decision`: Either `"accept"` or `"reject"`

409* `source`: Decision source - `"config"`, `"user_permanent"`, `"user_temporary"`, `"user_abort"`, or `"user_reject"`636* `source`: Decision source - `"config"`, `"hook"`, `"user_permanent"`, `"user_temporary"`, `"user_abort"`, or `"user_reject"`

637 

638#### Permission mode changed event

639 

640Logged when the permission mode changes, for example from `Shift+Tab` cycling, exiting plan mode, or an auto mode gate check.

641 

642**Event Name**: `claude_code.permission_mode_changed`

643 

644**Attributes**:

645 

646* All [standard attributes](#standard-attributes)

647* `event.name`: `"permission_mode_changed"`

648* `event.timestamp`: ISO 8601 timestamp

649* `event.sequence`: monotonically increasing counter for ordering events within a session

650* `from_mode`: The previous permission mode, for example `"default"`, `"plan"`, `"acceptEdits"`, `"auto"`, or `"bypassPermissions"`

651* `to_mode`: The new permission mode

652* `trigger`: What caused the change. One of `"shift_tab"`, `"exit_plan_mode"`, `"auto_gate_denied"`, or `"auto_opt_in"`. Absent when the transition originates from the SDK or bridge

653 

654#### Auth event

410 655 

411## Interpreting metrics and events data656Logged when `/login` or `/logout` completes.

412 657 

413The metrics exported by Claude Code provide valuable insights into usage patterns and productivity. Here are some common visualizations and analyses you can create:658**Event Name**: `claude_code.auth`

659 

660**Attributes**:

661 

662* All [standard attributes](#standard-attributes)

663* `event.name`: `"auth"`

664* `event.timestamp`: ISO 8601 timestamp

665* `event.sequence`: monotonically increasing counter for ordering events within a session

666* `action`: `"login"` or `"logout"`

667* `success`: `"true"` or `"false"`

668* `auth_method`: Authentication method, such as `"oauth"`

669* `error_category`: Categorical error kind when the action failed. The raw error message is never included

670* `status_code`: HTTP status code as a string when the action failed with an HTTP error

671 

672#### MCP server connection event

673 

674Logged when an MCP server connects, disconnects, or fails to connect.

675 

676**Event Name**: `claude_code.mcp_server_connection`

677 

678**Attributes**:

679 

680* All [standard attributes](#standard-attributes)

681* `event.name`: `"mcp_server_connection"`

682* `event.timestamp`: ISO 8601 timestamp

683* `event.sequence`: monotonically increasing counter for ordering events within a session

684* `status`: `"connected"`, `"failed"`, or `"disconnected"`

685* `transport_type`: Server transport, such as `"stdio"`, `"sse"`, or `"http"`

686* `server_scope`: Scope the server is configured at, such as `"user"`, `"project"`, or `"local"`

687* `duration_ms`: Connection attempt duration in milliseconds

688* `error_code`: Error code when the connection failed

689* `server_name` (when `OTEL_LOG_TOOL_DETAILS=1`): Configured server name

690* `error` (when `OTEL_LOG_TOOL_DETAILS=1`): Full error message when the connection failed

691 

692#### Internal error event

693 

694Logged when Claude Code catches an unexpected internal error. Only the error class name and an errno-style code are recorded. The error message and stack trace are never included. This event is not emitted when running against Bedrock, Vertex, or Foundry, or when `DISABLE_ERROR_REPORTING` is set.

695 

696**Event Name**: `claude_code.internal_error`

697 

698**Attributes**:

699 

700* All [standard attributes](#standard-attributes)

701* `event.name`: `"internal_error"`

702* `event.timestamp`: ISO 8601 timestamp

703* `event.sequence`: monotonically increasing counter for ordering events within a session

704* `error_name`: Error class name, such as `"TypeError"` or `"SyntaxError"`

705* `error_code`: Node.js errno code such as `"ENOENT"` when present on the error

706 

707#### Plugin installed event

708 

709Logged when a plugin finishes installing, from both the `claude plugin install` CLI command and the interactive `/plugin` UI.

710 

711**Event Name**: `claude_code.plugin_installed`

712 

713**Attributes**:

714 

715* All [standard attributes](#standard-attributes)

716* `event.name`: `"plugin_installed"`

717* `event.timestamp`: ISO 8601 timestamp

718* `event.sequence`: monotonically increasing counter for ordering events within a session

719* `marketplace.is_official`: `"true"` if the marketplace is an official Anthropic marketplace, `"false"` otherwise

720* `install.trigger`: `"cli"` or `"ui"`

721* `plugin.name`: Name of the installed plugin. For third-party marketplaces this is included only when `OTEL_LOG_TOOL_DETAILS=1`

722* `plugin.version`: Plugin version when declared in the marketplace entry. For third-party marketplaces this is included only when `OTEL_LOG_TOOL_DETAILS=1`

723* `marketplace.name`: Marketplace the plugin was installed from. For third-party marketplaces this is included only when `OTEL_LOG_TOOL_DETAILS=1`

724 

725#### Skill activated event

726 

727Logged when a skill is invoked.

728 

729**Event Name**: `claude_code.skill_activated`

730 

731**Attributes**:

732 

733* All [standard attributes](#standard-attributes)

734* `event.name`: `"skill_activated"`

735* `event.timestamp`: ISO 8601 timestamp

736* `event.sequence`: monotonically increasing counter for ordering events within a session

737* `skill.name`: Name of the skill. For user-defined and third-party plugin skills the value is the placeholder `"custom_skill"` unless `OTEL_LOG_TOOL_DETAILS=1`

738* `skill.source`: Where the skill was loaded from (for example, `"bundled"`, `"userSettings"`, `"projectSettings"`, `"plugin"`)

739* `plugin.name` (when `OTEL_LOG_TOOL_DETAILS=1` or the plugin is from an official marketplace): Name of the owning plugin when the skill is provided by a plugin

740* `marketplace.name` (when `OTEL_LOG_TOOL_DETAILS=1` or the plugin is from an official marketplace): Marketplace the owning plugin was installed from, when the skill is provided by a plugin

741 

742#### API retries exhausted event

743 

744Logged once when an API request fails after more than one attempt. Emitted alongside the final `api_error` event.

745 

746**Event Name**: `claude_code.api_retries_exhausted`

747 

748**Attributes**:

749 

750* All [standard attributes](#standard-attributes)

751* `event.name`: `"api_retries_exhausted"`

752* `event.timestamp`: ISO 8601 timestamp

753* `event.sequence`: monotonically increasing counter for ordering events within a session

754* `model`: Model used

755* `error`: Final error message

756* `status_code`: HTTP status code as a string

757* `total_attempts`: Total number of attempts made

758* `total_retry_duration_ms`: Total wall-clock time across all attempts

759* `speed`: `"fast"` or `"normal"`

760 

761#### Hook execution start event

762 

763Logged when one or more hooks begin executing for a hook event.

764 

765**Event Name**: `claude_code.hook_execution_start`

766 

767**Attributes**:

768 

769* All [standard attributes](#standard-attributes)

770* `event.name`: `"hook_execution_start"`

771* `event.timestamp`: ISO 8601 timestamp

772* `event.sequence`: monotonically increasing counter for ordering events within a session

773* `hook_event`: Hook event type, such as `"PreToolUse"` or `"PostToolUse"`

774* `hook_name`: Full hook name including matcher, such as `"PreToolUse:Write"`

775* `num_hooks`: Number of matching hook commands

776* `managed_only`: `"true"` when only managed-policy hooks are permitted

777* `hook_source`: `"policySettings"` or `"merged"`

778* `hook_definitions`: JSON-serialized hook configuration. Included only when both detailed beta tracing and `OTEL_LOG_TOOL_DETAILS=1` are enabled

779 

780#### Hook execution complete event

781 

782Logged when all hooks for a hook event have finished.

783 

784**Event Name**: `claude_code.hook_execution_complete`

785 

786**Attributes**:

787 

788* All [standard attributes](#standard-attributes)

789* `event.name`: `"hook_execution_complete"`

790* `event.timestamp`: ISO 8601 timestamp

791* `event.sequence`: monotonically increasing counter for ordering events within a session

792* `hook_event`: Hook event type

793* `hook_name`: Full hook name including matcher

794* `num_hooks`: Number of matching hook commands

795* `num_success`: Count that completed successfully

796* `num_blocking`: Count that returned a blocking decision

797* `num_non_blocking_error`: Count that failed without blocking

798* `num_cancelled`: Count cancelled before completion

799* `total_duration_ms`: Wall-clock duration of all matching hooks

800* `managed_only`: `"true"` when only managed-policy hooks are permitted

801* `hook_source`: `"policySettings"` or `"merged"`

802* `hook_definitions`: JSON-serialized hook configuration. Included only when both detailed beta tracing and `OTEL_LOG_TOOL_DETAILS=1` are enabled

803 

804#### Compaction event

805 

806Logged when conversation compaction completes.

807 

808**Event Name**: `claude_code.compaction`

809 

810**Attributes**:

811 

812* All [standard attributes](#standard-attributes)

813* `event.name`: `"compaction"`

814* `event.timestamp`: ISO 8601 timestamp

815* `event.sequence`: monotonically increasing counter for ordering events within a session

816* `trigger`: `"auto"` or `"manual"`

817* `success`: `"true"` or `"false"`

818* `duration_ms`: Compaction duration

819* `pre_tokens`: Approximate token count before compaction

820* `post_tokens`: Approximate token count after compaction

821* `error`: Error message when compaction failed

822 

823## Interpret metrics and events data

824 

825The exported metrics and events support a range of analyses:

414 826 

415### Usage monitoring827### Usage monitoring

416 828 


440* Unusual token consumption852* Unusual token consumption

441* High session volume from specific users853* High session volume from specific users

442 854 

443All metrics can be segmented by `user.account_uuid`, `organization.id`, `session.id`, `model`, and `app.version`.855All metrics can be segmented by `user.account_uuid`, `user.account_id`, `organization.id`, `session.id`, `model`, and `app.version`.

856 

857### Detect retry exhaustion

858 

859Claude Code retries failed API requests internally and emits a single `claude_code.api_error` event only after it gives up, so the event itself is the terminal signal for that request. Intermediate retry attempts are not logged as separate events.

860 

861The `attempt` attribute on the event records how many attempts were made in total. A value greater than `CLAUDE_CODE_MAX_RETRIES` (default `10`) indicates the request exhausted all retries on a transient error. A lower value indicates a non-retryable error such as a `400` response.

862 

863To distinguish a session that recovered from one that stalled, group events by `session.id` and check whether a later `api_request` event exists after the error.

444 864 

445### Event analysis865### Event analysis

446 866 


457 877 

458## Backend considerations878## Backend considerations

459 879 

460Your choice of metrics and logs backends determines the types of analyses you can perform:880Your choice of metrics, logs, and traces backends determines the types of analyses you can perform:

461 881 

462### For metrics882### For metrics

463 883 


471* **Columnar stores (for example, ClickHouse)**: Structured event analysis891* **Columnar stores (for example, ClickHouse)**: Structured event analysis

472* **Full-featured observability platforms (for example, Honeycomb, Datadog)**: Correlation between metrics and events892* **Full-featured observability platforms (for example, Honeycomb, Datadog)**: Correlation between metrics and events

473 893 

894### For traces

895 

896Choose a backend that supports distributed trace storage and span correlation:

897 

898* **Distributed tracing systems (for example, Jaeger, Zipkin, Grafana Tempo)**: Span visualization, request waterfalls, latency analysis

899* **Full-featured observability platforms (for example, Honeycomb, Datadog)**: Trace search and correlation with metrics and logs

900 

474For organizations requiring Daily/Weekly/Monthly Active User (DAU/WAU/MAU) metrics, consider backends that support efficient unique value queries.901For organizations requiring Daily/Weekly/Monthly Active User (DAU/WAU/MAU) metrics, consider backends that support efficient unique value queries.

475 902 

476## Service information903## Service information


489 916 

490For a comprehensive guide on measuring return on investment for Claude Code, including telemetry setup, cost analysis, productivity metrics, and automated reporting, see the [Claude Code ROI Measurement Guide](https://github.com/anthropics/claude-code-monitoring-guide). This repository provides ready-to-use Docker Compose configurations, Prometheus and OpenTelemetry setups, and templates for generating productivity reports integrated with tools like Linear.917For a comprehensive guide on measuring return on investment for Claude Code, including telemetry setup, cost analysis, productivity metrics, and automated reporting, see the [Claude Code ROI Measurement Guide](https://github.com/anthropics/claude-code-monitoring-guide). This repository provides ready-to-use Docker Compose configurations, Prometheus and OpenTelemetry setups, and templates for generating productivity reports integrated with tools like Linear.

491 918 

492## Security/privacy considerations919## Security and privacy

493 920 

494* Telemetry is opt-in and requires explicit configuration921* Telemetry is opt-in and requires explicit configuration

495* Sensitive information like API keys or file contents are never included in metrics or events922* Raw file contents and code snippets are not included in metrics or events. Trace spans are a separate data path: see the `OTEL_LOG_TOOL_CONTENT` bullet below

496* User prompt content is redacted by default - only prompt length is recorded. To enable user prompt logging, set `OTEL_LOG_USER_PROMPTS=1`923* When authenticated via OAuth, `user.email` is included in telemetry attributes. If this is a concern for your organization, work with your telemetry backend to filter or redact this field

497 924* User prompt content is not collected by default. Only prompt length is recorded. To include prompt content, set `OTEL_LOG_USER_PROMPTS=1`

498## Monitoring Claude Code on Amazon Bedrock925* Tool input arguments and parameters are not logged by default. To include them, set `OTEL_LOG_TOOL_DETAILS=1`. When enabled, `tool_result` events include a `tool_parameters` attribute with Bash commands, MCP server and tool names, and skill names, plus a `tool_input` attribute with file paths, URLs, search patterns, and other arguments. `user_prompt` events include the verbatim `command_name` for custom, plugin, and MCP commands. Trace spans include the same `tool_input` attribute and input-derived attributes such as `file_path`. Individual values over 512 characters are truncated and the total is bounded to \~4 K characters, but the arguments may still contain sensitive values. Configure your telemetry backend to filter or redact these attributes as needed

926* Tool input and output content is not logged in trace spans by default. To include it, set `OTEL_LOG_TOOL_CONTENT=1`. When enabled, span events include full tool input and output content truncated at 60 KB per span. This can include raw file contents from Read tool results and Bash command output. Configure your telemetry backend to filter or redact these attributes as needed

927* Raw Anthropic Messages API request and response bodies are not logged by default. To include them, set `OTEL_LOG_RAW_API_BODIES`. With `=1`, each API call emits `api_request_body` and `api_response_body` log events whose `body` attribute is the JSON-serialized payload, truncated at 60 KB. With `=file:<dir>`, untruncated bodies are written to `.request.json` and `.response.json` files under that directory and the events carry a `body_ref` path instead of the inline body. Ship the directory with a log collector or sidecar rather than through the telemetry stream. In both modes, bodies contain the full conversation history (system prompt, every prior user and assistant turn, tool results), so enabling this implies consent to everything the other `OTEL_LOG_*` content flags would reveal. Claude's extended-thinking content is always redacted from these bodies regardless of other settings

928 

929## Monitor Claude Code on Amazon Bedrock

499 930 

500For detailed Claude Code usage monitoring guidance for Amazon Bedrock, see [Claude Code Monitoring Implementation (Bedrock)](https://github.com/aws-solutions-library-samples/guidance-for-claude-code-with-amazon-bedrock/blob/main/assets/docs/MONITORING.md).931For detailed Claude Code usage monitoring guidance for Amazon Bedrock, see [Claude Code Monitoring Implementation (Bedrock)](https://github.com/aws-solutions-library-samples/guidance-for-claude-code-with-amazon-bedrock/blob/main/assets/docs/MONITORING.md).

Details

53 For proxies requiring advanced authentication (NTLM, Kerberos, etc.), consider using an LLM Gateway service that supports your authentication method.53 For proxies requiring advanced authentication (NTLM, Kerberos, etc.), consider using an LLM Gateway service that supports your authentication method.

54</Tip>54</Tip>

55 55 

56## CA certificate store

57 

58By default, Claude Code trusts both its bundled Mozilla CA certificates and your operating system's certificate store. Enterprise TLS-inspection proxies such as CrowdStrike Falcon and Zscaler work without additional configuration when their root certificate is installed in the OS trust store.

59 

60<Note>

61 System CA store integration requires the native Claude Code binary distribution. When running on the Node.js runtime, the system CA store is not merged automatically. In that case, set `NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem` to trust an enterprise root CA.

62</Note>

63 

64`CLAUDE_CODE_CERT_STORE` accepts a comma-separated list of sources. Recognized values are `bundled` for the Mozilla CA set shipped with Claude Code and `system` for the operating system trust store. The default is `bundled,system`.

65 

66To trust only the bundled Mozilla CA set:

67 

68```bash theme={null}

69export CLAUDE_CODE_CERT_STORE=bundled

70```

71 

72To trust only the OS certificate store:

73 

74```bash theme={null}

75export CLAUDE_CODE_CERT_STORE=system

76```

77 

78<Note>

79 `CLAUDE_CODE_CERT_STORE` has no dedicated `settings.json` schema key. Set it via the `env` block in `~/.claude/settings.json` or directly in the process environment.

80</Note>

81 

56## Custom CA certificates82## Custom CA certificates

57 83 

58If your enterprise environment uses custom CAs for HTTPS connections (whether through a proxy or direct API access), configure Claude Code to trust them:84If your enterprise environment uses a custom CA, configure Claude Code to trust it directly:

59 85 

60```bash theme={null}86```bash theme={null}

61export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem87export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem


78 104 

79## Network access requirements105## Network access requirements

80 106 

81Claude Code requires access to the following URLs:107Claude Code requires access to the following URLs. Allowlist these in your proxy configuration and firewall rules, especially in containerized or restricted network environments.

108 

109| URL | Required for |

110| ------------------------------ | ------------------------------------------------------------------------------------------------- |

111| `api.anthropic.com` | Claude API requests |

112| `claude.ai` | claude.ai account authentication |

113| `platform.claude.com` | Anthropic Console account authentication |

114| `downloads.claude.ai` | Plugin executable downloads; native installer and native auto-updater |

115| `storage.googleapis.com` | {/* max-version: 2.1.115 */}Native installer and native auto-updater on versions prior to 2.1.116 |

116| `bridge.claudeusercontent.com` | [Claude in Chrome](/en/chrome) extension WebSocket bridge |

117 

118If you install Claude Code through npm or manage your own binary distribution, end users may not need access to `downloads.claude.ai` or `storage.googleapis.com`.

119 

120Claude Code also sends optional operational telemetry by default, which you can disable with environment variables. See [Telemetry services](/en/data-usage#telemetry-services) for how to disable it before finalizing your allowlist.

121 

122When using [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), or [Microsoft Foundry](/en/microsoft-foundry), model traffic and authentication go to your provider instead of `api.anthropic.com`, `claude.ai`, or `platform.claude.com`. The WebFetch tool still calls `api.anthropic.com` for its [domain safety check](/en/data-usage#webfetch-domain-safety-check) unless you set `skipWebFetchPreflight: true` in [settings](/en/settings).

82 123 

83* `api.anthropic.com` - Claude API endpoints124[Claude Code on the web](/en/claude-code-on-the-web) and [Code Review](/en/code-review) connect to your repositories from Anthropic-managed infrastructure. If your GitHub Enterprise Cloud organization restricts access by IP address, enable [IP allow list inheritance for installed GitHub Apps](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization#allowing-access-by-github-apps). The Claude GitHub App registers its IP ranges, so enabling this setting allows access without manual configuration. To [add the ranges to your allow list manually](https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization#adding-an-allowed-ip-address) instead, or to configure other firewalls, see the [Anthropic API IP addresses](https://platform.claude.com/docs/en/api/ip-addresses).

84* `claude.ai` - WebFetch safeguards

85* `statsig.anthropic.com` - Telemetry and metrics

86* `sentry.io` - Error reporting

87 125 

88Ensure these URLs are allowlisted in your proxy configuration and firewall rules. This is especially important when using Claude Code in containerized or restricted network environments.126For self-hosted [GitHub Enterprise Server](/en/github-enterprise-server) instances behind a firewall, allowlist the same [Anthropic API IP addresses](https://platform.claude.com/docs/en/api/ip-addresses) so Anthropic infrastructure can reach your GHES host to clone repositories and post review comments.

89 127 

90## Additional resources128## Additional resources

91 129 

92* [Claude Code settings](/en/settings)130* [Claude Code settings](/en/settings)

93* [Environment variables reference](/en/settings#environment-variables)131* [Environment variables reference](/en/env-vars)

94* [Troubleshooting guide](/en/troubleshooting)132* [Troubleshooting guide](/en/troubleshooting)

output-styles.md +28 −17

Details

6 6 

7> Adapt Claude Code for uses beyond software engineering7> Adapt Claude Code for uses beyond software engineering

8 8 

9Output styles allow you to use Claude Code as any type of agent while keeping9Output styles change how Claude responds, not what Claude knows. They modify the system prompt to set role, tone, and output format while keeping core capabilities like running scripts, reading and writing files, and tracking TODOs. Use one when you keep re-prompting for the same voice or format every turn, or when you want Claude to act as something other than a software engineer.

10its core capabilities, such as running local scripts, reading/writing files, and10 

11tracking TODOs.11For instructions about your project, conventions, or codebase, use [CLAUDE.md](/en/memory) instead.

12 12 

13## Built-in output styles13## Built-in output styles

14 14 


31 31 

32Output styles directly modify Claude Code's system prompt.32Output styles directly modify Claude Code's system prompt.

33 33 

34* All output styles exclude instructions for efficient output (such as

35 responding concisely).

36* Custom output styles exclude instructions for coding (such as verifying code34* Custom output styles exclude instructions for coding (such as verifying code

37 with tests), unless `keep-coding-instructions` is true.35 with tests), unless `keep-coding-instructions` is true.

38* All output styles have their own custom instructions added to the end of the36* All output styles have their own custom instructions added to the end of the


40* All output styles trigger reminders for Claude to adhere to the output style38* All output styles trigger reminders for Claude to adhere to the output style

41 instructions during the conversation.39 instructions during the conversation.

42 40 

41Token usage depends on the style. Adding instructions to the system prompt

42increases input tokens, though prompt caching reduces this cost after the first

43request in a session. The built-in Explanatory and Learning styles produce

44longer responses than Default by design, which increases output tokens. For

45custom styles, output token usage depends on what your instructions tell Claude

46to produce.

47 

43## Change your output style48## Change your output style

44 49 

45You can either:50Run `/config` and select **Output style** to pick a style from a menu. Your

51selection is saved to `.claude/settings.local.json` at the

52[local project level](/en/settings).

46 53 

47* Run `/output-style` to access a menu and select your output style (this can54To set a style without the menu, edit the `outputStyle` field directly in a

48 also be accessed from the `/config` menu)55settings file:

49 56 

50* Run `/output-style [style]`, such as `/output-style explanatory`, to directly57```json theme={null}

51 switch to a style58{

59 "outputStyle": "Explanatory"

60}

61```

52 62 

53These changes apply to the [local project level](/en/settings) and are saved in63Because the output style is set in the system prompt at session start,

54`.claude/settings.local.json`. You can also directly edit the `outputStyle`64changes take effect the next time you start a new session. This keeps the system

55field in a settings file at a different level.65prompt stable throughout a conversation so prompt caching can reduce latency and

66cost.

56 67 

57## Create a custom output style68## Create a custom output style

58 69 


77```88```

78 89 

79You can save these files at the user level (`~/.claude/output-styles`) or90You can save these files at the user level (`~/.claude/output-styles`) or

80project level (`.claude/output-styles`).91project level (`.claude/output-styles`). [Plugins](/en/plugins-reference) can

92also ship output styles in an `output-styles/` directory.

81 93 

82### Frontmatter94### Frontmatter

83 95 

84Output style files support frontmatter, useful for specifying metadata about the96Output style files support frontmatter for specifying metadata:

85command:

86 97 

87| Frontmatter | Purpose | Default |98| Frontmatter | Purpose | Default |

88| :------------------------- | :-------------------------------------------------------------------------- | :---------------------- |99| :------------------------- | :-------------------------------------------------------------------------- | :---------------------- |

89| `name` | Name of the output style, if not the file name | Inherits from file name |100| `name` | Name of the output style, if not the file name | Inherits from file name |

90| `description` | Description of the output style. Used only in the UI of `/output-style` | None |101| `description` | Description of the output style, shown in the `/config` picker | None |

91| `keep-coding-instructions` | Whether to keep the parts of Claude Code's system prompt related to coding. | false |102| `keep-coding-instructions` | Whether to keep the parts of Claude Code's system prompt related to coding. | false |

92 103 

93## Comparisons to related features104## Comparisons to related features

overview.md +165 −80

Details

4 4 

5# Claude Code overview5# Claude Code overview

6 6 

7> Learn about Claude Code, Anthropic's agentic coding tool that lives in your terminal and helps you turn ideas into code faster than ever before.7> Claude Code is an agentic coding tool that reads your codebase, edits files, runs commands, and integrates with your development tools. Available in your terminal, IDE, desktop app, and browser.

8 8 

9## Get started in 30 seconds

10 9 

11Prerequisites:

12 10 

13* A [Claude subscription](https://claude.com/pricing) (Pro, Max, Teams, or Enterprise) or [Claude Console](https://console.anthropic.com/) account11Claude Code is an AI-powered coding assistant that helps you build features, fix bugs, and automate development tasks. It understands your entire codebase and can work across multiple files and tools to get things done.

14 12 

15**Install Claude Code:**

16 13 

17To install Claude Code, use one of the following methods:14 

15## Get started

16 

17Choose your environment to get started. Most surfaces require a [Claude subscription](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=overview_pricing) or [Anthropic Console](https://console.anthropic.com/) account. The Terminal CLI and VS Code also support [third-party providers](/en/third-party-integrations).

18 18 

19<Tabs>19<Tabs>

20 <Tab title="Terminal">

21 The full-featured CLI for working with Claude Code directly in your terminal. Edit files, run commands, and manage your entire project from the command line.

22 

23 To install Claude Code, use one of the following methods:

24 

25 <Tabs>

20 <Tab title="Native Install (Recommended)">26 <Tab title="Native Install (Recommended)">

21 **macOS, Linux, WSL:**27 **macOS, Linux, WSL:**

22 28 


36 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd42 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd

37 ```43 ```

38 44 

45 If you see `The token '&&' is not a valid statement separator`, you're in PowerShell, not CMD. If you see `'irm' is not recognized as an internal or external command`, you're in CMD, not PowerShell. Your prompt shows `PS C:\` when you're in PowerShell and `C:\` without the `PS` when you're in CMD.

46 

47 **Native Windows setups require [Git for Windows](https://git-scm.com/downloads/win).** Install it first if you don't have it. WSL setups do not need it.

48 

39 <Info>49 <Info>

40 Native installations automatically update in the background to keep you on the latest version.50 Native installations automatically update in the background to keep you on the latest version.

41 </Info>51 </Info>

42 </Tab>52 </Tab>

43 53 

44 <Tab title="Homebrew">54 <Tab title="Homebrew">

45 ```sh theme={null}55 ```bash theme={null}

46 brew install --cask claude-code56 brew install --cask claude-code

47 ```57 ```

48 58 

59 Homebrew offers two casks. `claude-code` tracks the stable release channel, which is typically about a week behind and skips releases with major regressions. `claude-code@latest` tracks the latest channel and receives new versions as soon as they ship.

60 

49 <Info>61 <Info>

50 Homebrew installations do not auto-update. Run `brew upgrade claude-code` periodically to get the latest features and security fixes.62 Homebrew installations do not auto-update. Run `brew upgrade claude-code` or `brew upgrade claude-code@latest`, depending on which cask you installed, to get the latest features and security fixes.

51 </Info>63 </Info>

52 </Tab>64 </Tab>

53 65 


60 WinGet installations do not auto-update. Run `winget upgrade Anthropic.ClaudeCode` periodically to get the latest features and security fixes.72 WinGet installations do not auto-update. Run `winget upgrade Anthropic.ClaudeCode` periodically to get the latest features and security fixes.

61 </Info>73 </Info>

62 </Tab>74 </Tab>

63</Tabs>75 </Tabs>

64 76 

65**Start using Claude Code:**77 You can also install with [apt, dnf, or apk](/en/setup#install-with-linux-package-managers) on Debian, Fedora, RHEL, and Alpine.

66 78 

67```bash theme={null}79 Then start Claude Code in any project:

68cd your-project

69claude

70```

71 80 

72You'll be prompted to log in on first use. That's it! [Continue with Quickstart (5 minutes) →](/en/quickstart)81 ```bash theme={null}

82 cd your-project

83 claude

84 ```

73 85 

74<Tip>86 You'll be prompted to log in on first use. That's it! [Continue with the Quickstart →](/en/quickstart)

87 

88 <Tip>

75 See [advanced setup](/en/setup) for installation options, manual updates, or uninstallation instructions. Visit [troubleshooting](/en/troubleshooting) if you hit issues.89 See [advanced setup](/en/setup) for installation options, manual updates, or uninstallation instructions. Visit [troubleshooting](/en/troubleshooting) if you hit issues.

76</Tip>90 </Tip>

91 </Tab>

77 92 

78## What Claude Code does for you93 <Tab title="VS Code">

94 The VS Code extension provides inline diffs, @-mentions, plan review, and conversation history directly in your editor.

79 95 

80* **Build features from descriptions**: Tell Claude what you want to build in plain English. It will make a plan, write the code, and ensure it works.96 * [Install for VS Code](vscode:extension/anthropic.claude-code)

81* **Debug and fix issues**: Describe a bug or paste an error message. Claude Code will analyze your codebase, identify the problem, and implement a fix.97 * [Install for Cursor](cursor:extension/anthropic.claude-code)

82* **Navigate any codebase**: Ask anything about your team's codebase, and get a thoughtful answer back. Claude Code maintains awareness of your entire project structure, can find up-to-date information from the web, and with [MCP](/en/mcp) can pull from external data sources like Google Drive, Figma, and Slack.

83* **Automate tedious tasks**: Fix fiddly lint issues, resolve merge conflicts, and write release notes. Do all this in a single command from your developer machines, or automatically in CI.

84 98 

85## Why developers love Claude Code99 Or search for "Claude Code" in the Extensions view (`Cmd+Shift+X` on Mac, `Ctrl+Shift+X` on Windows/Linux). After installing, open the Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`), type "Claude Code", and select **Open in New Tab**.

86 100 

87* **Works in your terminal**: Not another chat window. Not another IDE. Claude Code meets you where you already work, with the tools you already love.101 [Get started with VS Code →](/en/vs-code#get-started)

88* **Takes action**: Claude Code can directly edit files, run commands, and create commits. Need more? [MCP](/en/mcp) lets Claude read your design docs in Google Drive, update your tickets in Jira, or use *your* custom developer tooling.102 </Tab>

89* **Unix philosophy**: Claude Code is composable and scriptable. `tail -f app.log | claude -p "Slack me if you see any anomalies appear in this log stream"` *works*. Your CI can run `claude -p "If there are new text strings, translate them into French and raise a PR for @lang-fr-team to review"`.

90* **Enterprise-ready**: Use the Claude API, or host on AWS or GCP. Enterprise-grade [security](/en/security), [privacy](/en/data-usage), and [compliance](https://trust.anthropic.com/) is built-in.

91 103 

92## Use Claude Code everywhere104 <Tab title="Desktop app">

105 A standalone app for running Claude Code outside your IDE or terminal. Review diffs visually, run multiple sessions side by side, schedule recurring tasks, and kick off cloud sessions.

93 106 

94Claude Code works across your development environment: in your terminal, in your IDE, in the cloud, and in Slack.107 Download and install:

95 108 

96* **[Terminal (CLI)](/en/quickstart)**: the core Claude Code experience. Run `claude` in any terminal to start coding.109 * [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code\&utm_medium=docs) (Intel and Apple Silicon)

97* **[Claude Code on the web](/en/claude-code-on-the-web)**: use Claude Code from your browser at [claude.ai/code](https://claude.ai/code) or the Claude iOS app, with no local setup required. Run tasks in parallel, work on repos you don't have locally, and review changes in a built-in diff view.110 * [Windows](https://claude.ai/api/desktop/win32/x64/setup/latest/redirect?utm_source=claude_code\&utm_medium=docs) (x64)

98* **[Desktop app](/en/desktop)**: a standalone application with diff review, parallel sessions via git worktrees, and the ability to launch cloud sessions.111 * [Windows ARM64](https://claude.ai/api/desktop/win32/arm64/setup/latest/redirect?utm_source=claude_code\&utm_medium=docs)

99* **[VS Code](/en/vs-code)**: a native extension with inline diffs, @-mentions, and plan review.

100* **[JetBrains IDEs](/en/jetbrains)**: a plugin for IntelliJ IDEA, PyCharm, WebStorm, and other JetBrains IDEs with IDE diff viewing and context sharing.

101* **[GitHub Actions](/en/github-actions)**: automate code review, issue triage, and other workflows in CI/CD with `@claude` mentions.

102* **[GitLab CI/CD](/en/gitlab-ci-cd)**: event-driven automation for GitLab merge requests and issues.

103* **[Slack](/en/slack)**: mention Claude in Slack to route coding tasks to Claude Code on the web and get PRs back.

104* **[Chrome](/en/chrome)**: connect Claude Code to your browser for live debugging, design verification, and web app testing.

105 112 

106## Next steps113 After installing, launch Claude, sign in, and click the **Code** tab to start coding. A [paid subscription](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=overview_desktop_pricing) is required.

107 114 

108<CardGroup>115 [Learn more about the desktop app →](/en/desktop-quickstart)

109 <Card title="Quickstart" icon="rocket" href="/en/quickstart">116 </Tab>

110 See Claude Code in action with practical examples

111 </Card>

112 117 

113 <Card title="Common workflows" icon="graduation-cap" href="/en/common-workflows">118 <Tab title="Web">

114 Step-by-step guides for common workflows119 Run Claude Code in your browser with no local setup. Kick off long-running tasks and check back when they're done, work on repos you don't have locally, or run multiple tasks in parallel. Available on desktop browsers and the Claude iOS app.

115 </Card>

116 120 

117 <Card title="Troubleshooting" icon="wrench" href="/en/troubleshooting">121 Start coding at [claude.ai/code](https://claude.ai/code).

118 Solutions for common issues with Claude Code

119 </Card>

120 122 

121 <Card title="Desktop app" icon="laptop" href="/en/desktop">123 [Get started on the web →](/en/web-quickstart)

122 Run Claude Code as a standalone application124 </Tab>

123 </Card>

124</CardGroup>

125 125 

126## Additional resources126 <Tab title="JetBrains">

127 A plugin for IntelliJ IDEA, PyCharm, WebStorm, and other JetBrains IDEs with interactive diff viewing and selection context sharing.

127 128 

128<CardGroup>129 Install the [Claude Code plugin](https://plugins.jetbrains.com/plugin/27310-claude-code-beta-) from the JetBrains Marketplace and restart your IDE.

129 <Card title="About Claude Code" icon="sparkles" href="https://claude.com/product/claude-code">

130 Learn more about Claude Code on claude.com

131 </Card>

132 130 

133 <Card title="Build with the Agent SDK" icon="code-branch" href="https://docs.claude.com/en/docs/agent-sdk/overview">131 [Get started with JetBrains →](/en/jetbrains)

134 Create custom AI agents with the Claude Agent SDK132 </Tab>

135 </Card>133</Tabs>

136 134 

137 <Card title="Host on AWS or GCP" icon="cloud" href="/en/third-party-integrations">135## What you can do

138 Configure Claude Code with Amazon Bedrock or Google Vertex AI

139 </Card>

140 136 

141 <Card title="Settings" icon="gear" href="/en/settings">137Here are some of the ways you can use Claude Code:

142 Customize Claude Code for your workflow

143 </Card>

144 138 

145 <Card title="Commands" icon="terminal" href="/en/cli-reference">139<AccordionGroup>

146 Learn about CLI commands and controls140 <Accordion title="Automate the work you keep putting off" icon="wand-magic-sparkles">

147 </Card>141 Claude Code handles the tedious tasks that eat up your day: writing tests for untested code, fixing lint errors across a project, resolving merge conflicts, updating dependencies, and writing release notes.

148 142 

149 <Card title="Reference implementation" icon="code" href="https://github.com/anthropics/claude-code/tree/main/.devcontainer">143 ```bash theme={null}

150 Clone our development container reference implementation144 claude "write tests for the auth module, run them, and fix any failures"

151 </Card>145 ```

146 </Accordion>

147 

148 <Accordion title="Build features and fix bugs" icon="hammer">

149 Describe what you want in plain language. Claude Code plans the approach, writes the code across multiple files, and verifies it works.

150 

151 For bugs, paste an error message or describe the symptom. Claude Code traces the issue through your codebase, identifies the root cause, and implements a fix. See [common workflows](/en/common-workflows) for more examples.

152 </Accordion>

153 

154 <Accordion title="Create commits and pull requests" icon="code-branch">

155 Claude Code works directly with git. It stages changes, writes commit messages, creates branches, and opens pull requests.

156 

157 ```bash theme={null}

158 claude "commit my changes with a descriptive message"

159 ```

160 

161 In CI, you can automate code review and issue triage with [GitHub Actions](/en/github-actions) or [GitLab CI/CD](/en/gitlab-ci-cd).

162 </Accordion>

163 

164 <Accordion title="Connect your tools with MCP" icon="plug">

165 The [Model Context Protocol (MCP)](/en/mcp) is an open standard for connecting AI tools to external data sources. With MCP, Claude Code can read your design docs in Google Drive, update tickets in Jira, pull data from Slack, or use your own custom tooling.

166 </Accordion>

167 

168 <Accordion title="Customize with instructions, skills, and hooks" icon="sliders">

169 [`CLAUDE.md`](/en/memory) is a markdown file you add to your project root that Claude Code reads at the start of every session. Use it to set coding standards, architecture decisions, preferred libraries, and review checklists. Claude also builds [auto memory](/en/memory#auto-memory) as it works, saving learnings like build commands and debugging insights across sessions without you writing anything.

170 

171 Create [custom commands](/en/skills) to package repeatable workflows your team can share, like `/review-pr` or `/deploy-staging`.

172 

173 [Hooks](/en/hooks) let you run shell commands before or after Claude Code actions, like auto-formatting after every file edit or running lint before a commit.

174 </Accordion>

175 

176 <Accordion title="Run agent teams and build custom agents" icon="users">

177 Spawn [multiple Claude Code agents](/en/sub-agents) that work on different parts of a task simultaneously. A lead agent coordinates the work, assigns subtasks, and merges results.

178 

179 For fully custom workflows, the [Agent SDK](/en/agent-sdk/overview) lets you build your own agents powered by Claude Code's tools and capabilities, with full control over orchestration, tool access, and permissions.

180 </Accordion>

181 

182 <Accordion title="Pipe, script, and automate with the CLI" icon="terminal">

183 Claude Code is composable and follows the Unix philosophy. Pipe logs into it, run it in CI, or chain it with other tools:

184 

185 ```bash theme={null}

186 # Analyze recent log output

187 tail -200 app.log | claude -p "Slack me if you see any anomalies"

188 

189 # Automate translations in CI

190 claude -p "translate new strings into French and raise a PR for review"

191 

192 # Bulk operations across files

193 git diff main --name-only | claude -p "review these changed files for security issues"

194 ```

195 

196 See the [CLI reference](/en/cli-reference) for the full set of commands and flags.

197 </Accordion>

198 

199 <Accordion title="Schedule recurring tasks" icon="clock">

200 Run Claude on a schedule to automate work that repeats: morning PR reviews, overnight CI failure analysis, weekly dependency audits, or syncing docs after PRs merge.

201 

202 * [Routines](/en/routines) run on Anthropic-managed infrastructure, so they keep running even when your computer is off. They can also trigger on API calls or GitHub events. Create them from the web, the Desktop app, or by running `/schedule` in the CLI.

203 * [Desktop scheduled tasks](/en/desktop-scheduled-tasks) run on your machine, with direct access to your local files and tools

204 * [`/loop`](/en/scheduled-tasks) repeats a prompt within a CLI session for quick polling

205 </Accordion>

206 

207 <Accordion title="Work from anywhere" icon="globe">

208 Sessions aren't tied to a single surface. Move work between environments as your context changes:

209 

210 * Step away from your desk and keep working from your phone or any browser with [Remote Control](/en/remote-control)

211 * Message [Dispatch](/en/desktop#sessions-from-dispatch) a task from your phone and open the Desktop session it creates

212 * Kick off a long-running task on the [web](/en/claude-code-on-the-web) or [iOS app](https://apps.apple.com/app/claude-by-anthropic/id6473753684), then pull it into your terminal with `claude --teleport`

213 * Hand off a terminal session to the [Desktop app](/en/desktop) with `/desktop` for visual diff review

214 * Route tasks from team chat: mention `@Claude` in [Slack](/en/slack) with a bug report and get a pull request back

215 </Accordion>

216</AccordionGroup>

217 

218## Use Claude Code everywhere

219 

220Each surface connects to the same underlying Claude Code engine, so your CLAUDE.md files, settings, and MCP servers work across all of them.

221 

222Beyond 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:

223 

224| I want to... | Best option |

225| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |

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

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

228| 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) |

229| Run Claude on a recurring schedule | [Routines](/en/routines) or [Desktop scheduled tasks](/en/desktop-scheduled-tasks) |

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

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

232| Route bug reports from Slack to pull requests | [Slack](/en/slack) |

233| Debug live web applications | [Chrome](/en/chrome) |

234| Build custom agents for your own workflows | [Agent SDK](/en/agent-sdk/overview) |

235 

236## Next steps

152 237 

153 <Card title="Security" icon="shield" href="/en/security">238Once you've installed Claude Code, these guides help you go deeper.

154 Discover Claude Code's safeguards and best practices for safe usage

155 </Card>

156 239 

157 <Card title="Privacy and data usage" icon="lock" href="/en/data-usage">240* [Quickstart](/en/quickstart): walk through your first real task, from exploring a codebase to committing a fix

158 Understand how Claude Code handles your data241* [Store instructions and memories](/en/memory): give Claude persistent instructions with CLAUDE.md files and auto memory

159 </Card>242* [Common workflows](/en/common-workflows) and [best practices](/en/best-practices): patterns for getting the most out of Claude Code

160</CardGroup>243* [Settings](/en/settings): customize Claude Code for your workflow

244* [Troubleshooting](/en/troubleshooting): solutions for common issues

245* [code.claude.com](https://code.claude.com/): demos, pricing, and product details

permission-modes.md +288 −0 added

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# Choose a permission mode

6 

7> Control whether Claude asks before editing files or running commands. Cycle modes with Shift+Tab in the CLI or use the mode selector in VS Code, Desktop, and claude.ai.

8 

9When Claude wants to edit a file, run a shell command, or make a network request, it pauses and asks you to approve the action. Permission modes control how often that pause happens. The mode you pick shapes the flow of a session: default mode has you review each action as it comes, while looser modes let Claude work in longer uninterrupted stretches and report back when done. Pick more oversight for sensitive work, or fewer interruptions when you trust the direction.

10 

11## Available modes

12 

13Each mode makes a different tradeoff between convenience and oversight. The table below shows what Claude can do without a permission prompt in each mode.

14 

15| Mode | What runs without asking | Best for |

16| :------------------------------------------------------------------ | :------------------------------------------------------------------------------------- | :-------------------------------------- |

17| `default` | Reads only | Getting started, sensitive work |

18| [`acceptEdits`](#auto-approve-file-edits-with-acceptedits-mode) | Reads, file edits, and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.) | Iterating on code you're reviewing |

19| [`plan`](#analyze-before-you-edit-with-plan-mode) | Reads only | Exploring a codebase before changing it |

20| [`auto`](#eliminate-prompts-with-auto-mode) | Everything, with background safety checks | Long tasks, reducing prompt fatigue |

21| [`dontAsk`](#allow-only-pre-approved-tools-with-dontask-mode) | Only pre-approved tools | Locked-down CI and scripts |

22| [`bypassPermissions`](#skip-all-checks-with-bypasspermissions-mode) | Everything except protected paths | Isolated containers and VMs only |

23 

24Regardless of mode, writes to [protected paths](#protected-paths) are never auto-approved, guarding repository state and Claude's own configuration against accidental corruption.

25 

26Modes set the baseline. Layer [permission rules](/en/permissions#manage-permissions) on top to pre-approve or block specific tools in any mode except `bypassPermissions`, which skips the permission layer entirely.

27 

28## Switch permission modes

29 

30You can switch modes mid-session, at startup, or as a persistent default. The mode is set through these controls, not by asking Claude in chat. Select your interface below to see how to change it.

31 

32<Tabs>

33 <Tab title="CLI">

34 **During a session**: press `Shift+Tab` to cycle `default` → `acceptEdits` → `plan`. The current mode appears in the status bar. Not every mode is in the default cycle:

35 

36 * `auto`: appears when your account meets the [auto mode requirements](#eliminate-prompts-with-auto-mode); cycling to auto shows an opt-in prompt until you accept it, or select **No, don't ask again** to remove auto from the cycle

37 * `bypassPermissions`: appears after you start with `--permission-mode bypassPermissions`, `--dangerously-skip-permissions`, or `--allow-dangerously-skip-permissions`; the `--allow-` variant adds the mode to the cycle without activating it

38 * `dontAsk`: never appears in the cycle; set it with `--permission-mode dontAsk`

39 

40 Enabled optional modes slot in after `plan`, with `bypassPermissions` first and `auto` last. If you have both enabled, you will cycle through `bypassPermissions` on the way to `auto`.

41 

42 **At startup**: pass the mode as a flag.

43 

44 ```bash theme={null}

45 claude --permission-mode plan

46 ```

47 

48 **As a default**: set `defaultMode` in [settings](/en/settings#settings-files).

49 

50 ```json theme={null}

51 {

52 "permissions": {

53 "defaultMode": "acceptEdits"

54 }

55 }

56 ```

57 

58 The same `--permission-mode` flag works with `-p` for [non-interactive runs](/en/headless).

59 </Tab>

60 

61 <Tab title="VS Code">

62 **During a session**: click the mode indicator at the bottom of the prompt box.

63 

64 **As a default**: set `claudeCode.initialPermissionMode` in VS Code settings, or use the Claude Code extension settings panel.

65 

66 The mode indicator shows these labels, mapped to the mode each one applies:

67 

68 | UI label | Mode |

69 | :----------------- | :------------------ |

70 | Ask before edits | `default` |

71 | Edit automatically | `acceptEdits` |

72 | Plan mode | `plan` |

73 | Auto mode | `auto` |

74 | Bypass permissions | `bypassPermissions` |

75 

76 Auto mode appears in the mode indicator after you enable **Allow dangerously skip permissions** in the extension settings, but it stays unavailable until your account meets every requirement listed in the [auto mode section](#eliminate-prompts-with-auto-mode). The `claudeCode.initialPermissionMode` setting does not accept `auto`; to start in auto mode by default, set `defaultMode` in your Claude Code [`settings.json`](/en/settings#settings-files) instead.

77 

78 Bypass permissions also requires the **Allow dangerously skip permissions** toggle before it appears in the mode indicator.

79 

80 See the [VS Code guide](/en/vs-code) for extension-specific details.

81 </Tab>

82 

83 <Tab title="JetBrains">

84 The JetBrains plugin runs Claude Code in the IDE terminal, so switching modes works the same as in the CLI: press `Shift+Tab` to cycle, or pass `--permission-mode` when launching.

85 </Tab>

86 

87 <Tab title="Desktop">

88 Use the mode selector next to the send button. Auto and Bypass permissions appear only after you enable them in Desktop settings. See the [Desktop guide](/en/desktop#choose-a-permission-mode).

89 </Tab>

90 

91 <Tab title="Web and mobile">

92 Use the mode dropdown next to the prompt box on [claude.ai/code](https://claude.ai/code) or in the mobile app. Permission prompts appear in claude.ai for approval. Which modes appear depends on where the session runs:

93 

94 * **Cloud sessions** on [Claude Code on the web](/en/claude-code-on-the-web): Auto accept edits and Plan mode. Ask permissions, Auto, and Bypass permissions are not available.

95 * **[Remote Control](/en/remote-control) sessions** on your local machine: Ask permissions, Auto accept edits, and Plan mode. Auto and Bypass permissions are not available.

96 

97 For Remote Control, you can also set the starting mode when launching the host:

98 

99 ```bash theme={null}

100 claude remote-control --permission-mode acceptEdits

101 ```

102 </Tab>

103</Tabs>

104 

105## Auto-approve file edits with acceptEdits mode

106 

107`acceptEdits` mode lets Claude create and edit files in your working directory without prompting. The status bar shows `⏵⏵ accept edits on` while this mode is active.

108 

109In addition to file edits, `acceptEdits` mode auto-approves common filesystem Bash commands: `mkdir`, `touch`, `rm`, `rmdir`, `mv`, `cp`, and `sed`. These commands are also auto-approved when prefixed with safe environment variables such as `LANG=C` or `NO_COLOR=1`, or process wrappers such as `timeout`, `nice`, or `nohup`. Like file edits, auto-approval applies only to paths inside your working directory or `additionalDirectories`. Paths outside that scope, writes to [protected paths](#protected-paths), and all other Bash commands still prompt.

110 

111Use `acceptEdits` when you want to review changes in your editor or via `git diff` after the fact rather than approving each edit inline. Press `Shift+Tab` once from default mode to enter it, or start with it directly:

112 

113```bash theme={null}

114claude --permission-mode acceptEdits

115```

116 

117## Analyze before you edit with plan mode

118 

119Plan mode tells Claude to research and propose changes without making them. Claude reads files, runs shell commands to explore, and writes a plan, but does not edit your source. Permission prompts still apply the same as default mode.

120 

121Enter plan mode by pressing `Shift+Tab` or prefixing a single prompt with `/plan`. You can also start in plan mode from the CLI:

122 

123```bash theme={null}

124claude --permission-mode plan

125```

126 

127Press `Shift+Tab` again to leave plan mode without approving a plan.

128 

129When the plan is ready, Claude presents it and asks how to proceed. From that prompt you can:

130 

131* Approve and start in auto mode

132* Approve and accept edits

133* Approve and review each edit manually

134* Keep planning with feedback

135* Refine with [Ultraplan](/en/ultraplan) for browser-based review

136 

137Each approve option also offers to clear the planning context first.

138 

139## Eliminate prompts with auto mode

140 

141<Note>

142 Auto mode requires Claude Code v2.1.83 or later.

143</Note>

144 

145Auto mode lets Claude execute without permission prompts. A separate classifier model reviews actions before they run, blocking anything that escalates beyond your request, targets unrecognized infrastructure, or appears driven by hostile content Claude read.

146 

147<Warning>

148 Auto mode is a research preview. It reduces prompts but does not guarantee safety. Use it for tasks where you trust the general direction, not as a replacement for review on sensitive operations.

149</Warning>

150 

151Auto mode is available only when your account meets all of these requirements:

152 

153* **Plan**: Max, Team, Enterprise, or API. Not available on Pro.

154* **Admin**: on Team and Enterprise, an admin must enable it in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code) before users can turn it on. Admins can also lock it off by setting `permissions.disableAutoMode` to `"disable"` in [managed settings](/en/permissions#managed-settings).

155* **Model**: Claude Sonnet 4.6, Opus 4.6, or Opus 4.7 on Team, Enterprise, and API plans; Claude Opus 4.7 only on Max plans. Other models, including Haiku and claude-3 models, are not supported.

156* **Provider**: Anthropic API only. Not available on Bedrock, Vertex, or Foundry.

157 

158If Claude Code reports auto mode as unavailable, one of these requirements is unmet; this is not a transient outage. A separate message that names a model and says auto mode "cannot determine the safety" of an action is a transient classifier outage; see the [error reference](/en/errors#auto-mode-cannot-determine-the-safety-of-an-action).

159 

160### What the classifier blocks by default

161 

162The classifier trusts your working directory and your repo's configured remotes. Everything else is treated as external until you [configure trusted infrastructure](/en/auto-mode-config).

163 

164**Blocked by default**:

165 

166* Downloading and executing code, like `curl | bash`

167* Sending sensitive data to external endpoints

168* Production deploys and migrations

169* Mass deletion on cloud storage

170* Granting IAM or repo permissions

171* Modifying shared infrastructure

172* Irreversibly destroying files that existed before the session

173* Force push, or pushing directly to `main`

174 

175**Allowed by default**:

176 

177* Local file operations in your working directory

178* Installing dependencies declared in your lock files or manifests

179* Reading `.env` and sending credentials to their matching API

180* Read-only HTTP requests

181* Pushing to the branch you started on or one Claude created

182 

183Sandbox network access requests are routed through the classifier rather than allowed by default. Run `claude auto-mode defaults` to see the full rule lists. If routine actions get blocked, an administrator can add trusted repos, buckets, and services via the `autoMode.environment` setting: see [Configure auto mode](/en/auto-mode-config).

184 

185### Boundaries you state in conversation

186 

187The classifier treats boundaries you state in the conversation as a block signal. If you tell Claude "don't push" or "wait until I review before deploying", the classifier blocks matching actions even when the default rules would allow them. A boundary stays in force until you lift it in a later message. Claude's own judgment that a condition was met does not lift it.

188 

189Boundaries are not stored as rules. The classifier re-reads them from the transcript on each check, so a boundary can be lost if [context compaction](/en/costs#reduce-token-usage) removes the message that stated it. For a hard guarantee, add a [deny rule](/en/permissions#permission-rule-syntax) instead.

190 

191### When auto mode falls back

192 

193Each denied action shows a notification and appears in `/permissions` under the Recently denied tab, where you can press `r` to retry it with a manual approval.

194 

195If the classifier blocks an action 3 times in a row or 20 times total, auto mode pauses and Claude Code resumes prompting. Approving the prompted action resumes auto mode. These thresholds are not configurable. Any allowed action resets the consecutive counter, while the total counter persists for the session and resets only when its own limit triggers a fallback.

196 

197In [non-interactive mode](/en/headless) with the `-p` flag, repeated blocks abort the session since there is no user to prompt.

198 

199Repeated blocks usually mean the classifier is missing context about your infrastructure. Use `/feedback` to report false positives, or have an administrator [configure trusted infrastructure](/en/auto-mode-config).

200 

201<AccordionGroup>

202 <Accordion title="How the classifier evaluates actions">

203 Each action goes through a fixed decision order. The first matching step wins:

204 

205 1. Actions matching your [allow or deny rules](/en/permissions#manage-permissions) resolve immediately

206 2. Read-only actions and file edits in your working directory are auto-approved, except writes to [protected paths](#protected-paths)

207 3. Everything else goes to the classifier

208 4. If the classifier blocks, Claude receives the reason and tries an alternative

209 

210 On entering auto mode, broad allow rules that grant arbitrary code execution are dropped:

211 

212 * Blanket `Bash(*)` or `PowerShell(*)`

213 * Wildcarded interpreters like `Bash(python*)`

214 * Package-manager run commands

215 * `Agent` allow rules

216 

217 Narrow rules like `Bash(npm test)` carry over. Dropped rules are restored when you leave auto mode.

218 

219 The classifier sees user messages, tool calls, and your CLAUDE.md content. Tool results are stripped, so hostile content in a file or web page cannot manipulate it directly. A separate server-side probe scans incoming tool results and flags suspicious content before Claude reads it. For more on how these layers work together, see the [auto mode announcement](https://claude.com/blog/auto-mode) and the [engineering deep dive](https://www.anthropic.com/engineering/claude-code-auto-mode).

220 </Accordion>

221 

222 <Accordion title="How auto mode handles subagents">

223 The classifier checks [subagent](/en/sub-agents) work at three points:

224 

225 1. Before a subagent starts, the delegated task description is evaluated, so a dangerous-looking task is blocked at spawn time.

226 2. While the subagent runs, each of its actions goes through the classifier with the same rules as the parent session, and any `permissionMode` in the subagent's frontmatter is ignored.

227 3. When the subagent finishes, the classifier reviews its full action history; if that return check flags a concern, a security warning is prepended to the subagent's results.

228 </Accordion>

229 

230 <Accordion title="Cost and latency">

231 The classifier runs on a server-configured model that is independent of your `/model` selection, so switching models does not change classifier availability. Classifier calls count toward your token usage. Each check sends a portion of the transcript plus the pending action, adding a round-trip before execution. Reads and working-directory edits outside protected paths skip the classifier, so the overhead comes mainly from shell commands and network operations.

232 </Accordion>

233</AccordionGroup>

234 

235## Allow only pre-approved tools with dontAsk mode

236 

237`dontAsk` mode auto-denies every tool call that would otherwise prompt. Only actions matching your `permissions.allow` rules and [read-only Bash commands](/en/permissions#read-only-commands) can execute; explicit `ask` rules are denied rather than prompting. This makes the mode fully non-interactive for CI pipelines or restricted environments where you pre-define exactly what Claude may do.

238 

239Set it at startup with the flag:

240 

241```bash theme={null}

242claude --permission-mode dontAsk

243```

244 

245## Skip all checks with bypassPermissions mode

246 

247`bypassPermissions` mode disables permission prompts and safety checks so tool calls execute immediately. Writes to [protected paths](#protected-paths) are the only actions that still prompt. Only use this mode in isolated environments like containers, VMs, or dev containers without internet access, where Claude Code cannot damage your host system.

248 

249You cannot enter `bypassPermissions` from a session that was started without one of the enabling flags; restart with one to enable it:

250 

251```bash theme={null}

252claude --permission-mode bypassPermissions

253```

254 

255The `--dangerously-skip-permissions` flag is equivalent.

256 

257<Warning>

258 `bypassPermissions` offers no protection against prompt injection or unintended actions. For background safety checks without prompts, use [auto mode](#eliminate-prompts-with-auto-mode) instead. Administrators can block this mode by setting `permissions.disableBypassPermissionsMode` to `"disable"` in [managed settings](/en/permissions#managed-settings).

259</Warning>

260 

261## Protected paths

262 

263Writes to a small set of paths are never auto-approved, in every mode. This prevents accidental corruption of repository state and Claude's own configuration. In `default`, `acceptEdits`, `plan`, and `bypassPermissions` these writes prompt; in `auto` they route to the classifier; in `dontAsk` they are denied.

264 

265Protected directories:

266 

267* `.git`

268* `.vscode`

269* `.idea`

270* `.husky`

271* `.claude`, except for `.claude/commands`, `.claude/agents`, `.claude/skills`, and `.claude/worktrees` where Claude routinely creates content

272 

273Protected files:

274 

275* `.gitconfig`, `.gitmodules`

276* `.bashrc`, `.bash_profile`, `.zshrc`, `.zprofile`, `.profile`

277* `.ripgreprc`

278* `.mcp.json`, `.claude.json`

279 

280## See also

281 

282* [Permissions](/en/permissions): allow, ask, and deny rules; managed policies

283* [Configure auto mode](/en/auto-mode-config): tell the classifier which infrastructure your organization trusts

284* [Hooks](/en/hooks): custom permission logic via `PreToolUse` and `PermissionRequest` hooks

285* [Ultraplan](/en/ultraplan): run plan mode in a Claude Code on the web session with browser-based review

286* [Security](/en/security): safeguards and best practices

287* [Sandboxing](/en/sandboxing): filesystem and network isolation for Bash commands

288* [Non-interactive mode](/en/headless): run Claude Code with the `-p` flag

permissions.md +336 −0 added

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# Configure permissions

6 

7> Control what Claude Code can access and do with fine-grained permission rules, modes, and managed policies.

8 

9Claude Code supports fine-grained permissions so that you can specify exactly what the agent is allowed to do and what it cannot. Permission settings can be checked into version control and distributed to all developers in your organization, as well as customized by individual developers.

10 

11## Permission system

12 

13Claude Code uses a tiered permission system to balance power and safety:

14 

15| Tool type | Example | Approval required | "Yes, don't ask again" behavior |

16| :---------------- | :--------------- | :---------------- | :-------------------------------------------- |

17| Read-only | File reads, Grep | No | N/A |

18| Bash commands | Shell execution | Yes | Permanently per project directory and command |

19| File modification | Edit/write files | Yes | Until session end |

20 

21## Manage permissions

22 

23You can view and manage Claude Code's tool permissions with `/permissions`. This UI lists all permission rules and the settings.json file they are sourced from.

24 

25* **Allow** rules let Claude Code use the specified tool without manual approval.

26* **Ask** rules prompt for confirmation whenever Claude Code tries to use the specified tool.

27* **Deny** rules prevent Claude Code from using the specified tool.

28 

29Rules are evaluated in order: **deny -> ask -> allow**. The first matching rule wins, so deny rules always take precedence.

30 

31## Permission modes

32 

33Claude Code supports several permission modes that control how tools are approved. See [Permission modes](/en/permission-modes) for when to use each one. Set the `defaultMode` in your [settings files](/en/settings#settings-files):

34 

35| Mode | Description |

36| :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |

37| `default` | Standard behavior: prompts for permission on first use of each tool |

38| `acceptEdits` | Automatically accepts file edits and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.) for paths in the working directory or `additionalDirectories` |

39| `plan` | Plan Mode: Claude can analyze but not modify files or execute commands |

40| `auto` | Auto-approves tool calls with background safety checks that verify actions align with your request. Currently a research preview |

41| `dontAsk` | Auto-denies tools unless pre-approved via `/permissions` or `permissions.allow` rules |

42| `bypassPermissions` | Skips permission prompts except for writes to protected directories (see warning below) |

43 

44<Warning>

45 `bypassPermissions` mode skips permission prompts. Writes to `.git`, `.claude`, `.vscode`, `.idea`, and `.husky` directories still prompt for confirmation to prevent accidental corruption of repository state, editor configuration, and git hooks. Writes to `.claude/commands`, `.claude/agents`, and `.claude/skills` are exempt and do not prompt, because Claude routinely writes there when creating skills, subagents, and commands. Only use this mode in isolated environments like containers or VMs where Claude Code cannot cause damage. Administrators can prevent this mode by setting `permissions.disableBypassPermissionsMode` to `"disable"` in [managed settings](#managed-settings).

46</Warning>

47 

48To prevent `bypassPermissions` or `auto` mode from being used, set `permissions.disableBypassPermissionsMode` or `permissions.disableAutoMode` to `"disable"` in any [settings file](/en/settings#settings-files). These are most useful in [managed settings](#managed-settings) where they cannot be overridden.

49 

50## Permission rule syntax

51 

52Permission rules follow the format `Tool` or `Tool(specifier)`.

53 

54### Match all uses of a tool

55 

56To match all uses of a tool, use just the tool name without parentheses:

57 

58| Rule | Effect |

59| :--------- | :----------------------------- |

60| `Bash` | Matches all Bash commands |

61| `WebFetch` | Matches all web fetch requests |

62| `Read` | Matches all file reads |

63 

64`Bash(*)` is equivalent to `Bash` and matches all Bash commands.

65 

66### Use specifiers for fine-grained control

67 

68Add a specifier in parentheses to match specific tool uses:

69 

70| Rule | Effect |

71| :----------------------------- | :------------------------------------------------------- |

72| `Bash(npm run build)` | Matches the exact command `npm run build` |

73| `Read(./.env)` | Matches reading the `.env` file in the current directory |

74| `WebFetch(domain:example.com)` | Matches fetch requests to example.com |

75 

76### Wildcard patterns

77 

78Bash rules support glob patterns with `*`. Wildcards can appear at any position in the command. This configuration allows npm and git commit commands while blocking git push:

79 

80```json theme={null}

81{

82 "permissions": {

83 "allow": [

84 "Bash(npm run *)",

85 "Bash(git commit *)",

86 "Bash(git * main)",

87 "Bash(* --version)",

88 "Bash(* --help *)"

89 ],

90 "deny": [

91 "Bash(git push *)"

92 ]

93 }

94}

95```

96 

97The space before `*` matters: `Bash(ls *)` matches `ls -la` but not `lsof`, while `Bash(ls*)` matches both. The `:*` suffix is an equivalent way to write a trailing wildcard, so `Bash(ls:*)` matches the same commands as `Bash(ls *)`.

98 

99The permission dialog writes the space-separated form when you select "Yes, don't ask again" for a command prefix. The `:*` form is only recognized at the end of a pattern. In a pattern like `Bash(git:* push)`, the colon is treated as a literal character and won't match git commands.

100 

101## Tool-specific permission rules

102 

103### Bash

104 

105Bash permission rules support wildcard matching with `*`. Wildcards can appear at any position in the command, including at the beginning, middle, or end:

106 

107* `Bash(npm run build)` matches the exact Bash command `npm run build`

108* `Bash(npm run test *)` matches Bash commands starting with `npm run test`

109* `Bash(npm *)` matches any command starting with `npm `

110* `Bash(* install)` matches any command ending with ` install`

111* `Bash(git * main)` matches commands like `git checkout main` and `git log --oneline main`

112 

113A single `*` matches any sequence of characters including spaces, so one wildcard can span multiple arguments. `Bash(git *)` matches `git log --oneline --all`, and `Bash(git * main)` matches `git push origin main` as well as `git merge main`.

114 

115When `*` appears at the end with a space before it (like `Bash(ls *)`), it enforces a word boundary, requiring the prefix to be followed by a space or end-of-string. For example, `Bash(ls *)` matches `ls -la` but not `lsof`. In contrast, `Bash(ls*)` without a space matches both `ls -la` and `lsof` because there's no word boundary constraint.

116 

117#### Compound commands

118 

119<Tip>

120 Claude Code is aware of shell operators, so a rule like `Bash(safe-cmd *)` won't give it permission to run the command `safe-cmd && other-cmd`. The recognized command separators are `&&`, `||`, `;`, `|`, `|&`, `&`, and newlines. A rule must match each subcommand independently.

121</Tip>

122 

123When you approve a compound command with "Yes, don't ask again", Claude Code saves a separate rule for each subcommand that requires approval, rather than a single rule for the full compound string. For example, approving `git status && npm test` saves a rule for `npm test`, so future `npm test` invocations are recognized regardless of what precedes the `&&`. Subcommands like `cd` into a subdirectory generate their own Read rule for that path. Up to 5 rules may be saved for a single compound command.

124 

125#### Process wrappers

126 

127Before matching Bash rules, Claude Code strips a fixed set of process wrappers so a rule like `Bash(npm test *)` also matches `timeout 30 npm test`. The recognized wrappers are `timeout`, `time`, `nice`, `nohup`, and `stdbuf`.

128 

129Bare `xargs` is also stripped, so `Bash(grep *)` matches `xargs grep pattern`. Stripping applies only when `xargs` has no flags: an invocation like `xargs -n1 grep pattern` is matched as an `xargs` command, so rules written for the inner command do not cover it.

130 

131This wrapper list is built in and is not configurable. Development environment runners such as `direnv exec`, `devbox run`, `mise exec`, `npx`, and `docker exec` are not in the list. Because these tools execute their arguments as a command, a rule like `Bash(devbox run *)` matches whatever comes after `run`, including `devbox run rm -rf .`. To approve work inside an environment runner, write a specific rule that includes both the runner and the inner command, such as `Bash(devbox run npm test)`. Add one rule per inner command you want to allow.

132 

133Exec wrappers such as `watch`, `setsid`, `ionice`, and `flock` always prompt and cannot be auto-approved by a prefix rule like `Bash(watch *)`. The same applies to `find` with `-exec` or `-delete`: a `Bash(find *)` rule does not cover these forms. To approve a specific invocation, write an exact-match rule for the full command string.

134 

135#### Read-only commands

136 

137Claude Code recognizes a built-in set of Bash commands as read-only and runs them without a permission prompt in every mode. These include `ls`, `cat`, `head`, `tail`, `grep`, `find`, `wc`, `diff`, `stat`, `du`, `cd`, and read-only forms of `git`. The set is not configurable; to require a prompt for one of these commands, add an `ask` or `deny` rule for it.

138 

139Unquoted glob patterns are permitted for commands whose every flag is read-only, so `ls *.ts` and `wc -l src/*.py` run without a prompt. Commands with write-capable or exec-capable flags, such as `find`, `sort`, `sed`, and `git`, still prompt when an unquoted glob is present because the glob could expand to a flag like `-delete`.

140 

141A `cd` into a path inside your working directory or an [additional directory](#working-directories) is also read-only. A compound command like `cd packages/api && ls` runs without a prompt when each part qualifies on its own. Combining `cd` with `git` in one compound command always prompts, regardless of the target directory.

142 

143<Warning>

144 Bash permission patterns that try to constrain command arguments are fragile. For example, `Bash(curl http://github.com/ *)` intends to restrict curl to GitHub URLs, but won't match variations like:

145 

146 * Options before URL: `curl -X GET http://github.com/...`

147 * Different protocol: `curl https://github.com/...`

148 * Redirects: `curl -L http://bit.ly/xyz` (redirects to github)

149 * Variables: `URL=http://github.com && curl $URL`

150 * Extra spaces: `curl http://github.com`

151 

152 For more reliable URL filtering, consider:

153 

154 * **Restrict Bash network tools**: use deny rules to block `curl`, `wget`, and similar commands, then use the WebFetch tool with `WebFetch(domain:github.com)` permission for allowed domains

155 * **Use PreToolUse hooks**: implement a hook that validates URLs in Bash commands and blocks disallowed domains

156 * Instructing Claude Code about your allowed curl patterns via CLAUDE.md

157 

158 Note that using WebFetch alone does not prevent network access. If Bash is allowed, Claude can still use `curl`, `wget`, or other tools to reach any URL.

159</Warning>

160 

161### Read and Edit

162 

163`Edit` rules apply to all built-in tools that edit files. Claude makes a best-effort attempt to apply `Read` rules to all built-in tools that read files like Grep and Glob.

164 

165<Warning>

166 Read and Edit deny rules apply to Claude's built-in file tools, not to Bash subprocesses. A `Read(./.env)` deny rule blocks the Read tool but does not prevent `cat .env` in Bash. For OS-level enforcement that blocks all processes from accessing a path, [enable the sandbox](/en/sandboxing).

167</Warning>

168 

169Read and Edit rules both follow the [gitignore](https://git-scm.com/docs/gitignore) specification with four distinct pattern types:

170 

171| Pattern | Meaning | Example | Matches |

172| ------------------ | -------------------------------------- | -------------------------------- | ------------------------------ |

173| `//path` | **Absolute** path from filesystem root | `Read(//Users/alice/secrets/**)` | `/Users/alice/secrets/**` |

174| `~/path` | Path from **home** directory | `Read(~/Documents/*.pdf)` | `/Users/alice/Documents/*.pdf` |

175| `/path` | Path **relative to project root** | `Edit(/src/**/*.ts)` | `<project root>/src/**/*.ts` |

176| `path` or `./path` | Path **relative to current directory** | `Read(*.env)` | `<cwd>/*.env` |

177 

178<Warning>

179 A pattern like `/Users/alice/file` is NOT an absolute path. It's relative to the project root. Use `//Users/alice/file` for absolute paths.

180</Warning>

181 

182On Windows, paths are normalized to POSIX form before matching. `C:\Users\alice` becomes `/c/Users/alice`, so use `//c/**/.env` to match `.env` files anywhere on that drive. To match across all drives, use `//**/.env`.

183 

184Examples:

185 

186* `Edit(/docs/**)`: edits in `<project>/docs/` (NOT `/docs/` and NOT `<project>/.claude/docs/`)

187* `Read(~/.zshrc)`: reads your home directory's `.zshrc`

188* `Edit(//tmp/scratch.txt)`: edits the absolute path `/tmp/scratch.txt`

189* `Read(src/**)`: reads from `<current-directory>/src/`

190 

191<Note>

192 In gitignore patterns, `*` matches files in a single directory while `**` matches recursively across directories. To allow all file access, use just the tool name without parentheses: `Read`, `Edit`, or `Write`.

193</Note>

194 

195When Claude accesses a symlink, permission rules check two paths: the symlink itself and the file it resolves to. Allow and deny rules treat that pair differently: allow rules fall back to prompting you, while deny rules block outright.

196 

197* **Allow rules**: apply only when both the symlink path and its target match. A symlink inside an allowed directory that points outside it still prompts you.

198* **Deny rules**: apply when either the symlink path or its target matches. A symlink that points to a denied file is itself denied.

199 

200For example, with `Read(./project/**)` allowed and `Read(~/.ssh/**)` denied, a symlink at `./project/key` pointing to `~/.ssh/id_rsa` is blocked: the target fails the allow rule and matches the deny rule.

201 

202### WebFetch

203 

204* `WebFetch(domain:example.com)` matches fetch requests to example.com

205 

206### MCP

207 

208* `mcp__puppeteer` matches any tool provided by the `puppeteer` server (name configured in Claude Code)

209* `mcp__puppeteer__*` wildcard syntax that also matches all tools from the `puppeteer` server

210* `mcp__puppeteer__puppeteer_navigate` matches the `puppeteer_navigate` tool provided by the `puppeteer` server

211 

212### Agent (subagents)

213 

214Use `Agent(AgentName)` rules to control which [subagents](/en/sub-agents) Claude can use:

215 

216* `Agent(Explore)` matches the Explore subagent

217* `Agent(Plan)` matches the Plan subagent

218* `Agent(my-custom-agent)` matches a custom subagent named `my-custom-agent`

219 

220Add these rules to the `deny` array in your settings or use the `--disallowedTools` CLI flag to disable specific agents. To disable the Explore agent:

221 

222```json theme={null}

223{

224 "permissions": {

225 "deny": ["Agent(Explore)"]

226 }

227}

228```

229 

230## Extend permissions with hooks

231 

232[Claude Code hooks](/en/hooks-guide) provide a way to register custom shell commands to perform permission evaluation at runtime. When Claude Code makes a tool call, PreToolUse hooks run before the permission prompt. The hook output can deny the tool call, force a prompt, or skip the prompt to let the call proceed.

233 

234Hook decisions do not bypass permission rules. Deny and ask rules are evaluated regardless of what a PreToolUse hook returns, so a matching deny rule blocks the call and a matching ask rule still prompts even when the hook returned `"allow"` or `"ask"`. This preserves the deny-first precedence described in [Manage permissions](#manage-permissions), including deny rules set in managed settings.

235 

236A blocking hook also takes precedence over allow rules. A hook that exits with code 2 stops the tool call before permission rules are evaluated, so the block applies even when an allow rule would otherwise let the call proceed. To run all Bash commands without prompts except for a few you want blocked, add `"Bash"` to your allow list and register a PreToolUse hook that rejects those specific commands. See [Block edits to protected files](/en/hooks-guide#block-edits-to-protected-files) for a hook script you can adapt.

237 

238## Working directories

239 

240By default, Claude has access to files in the directory where it was launched. You can extend this access:

241 

242* **During startup**: use `--add-dir <path>` CLI argument

243* **During session**: use `/add-dir` command

244* **Persistent configuration**: add to `additionalDirectories` in [settings files](/en/settings#settings-files)

245 

246Files in additional directories follow the same permission rules as the original working directory: they become readable without prompts, and file editing permissions follow the current permission mode.

247 

248### Additional directories grant file access, not configuration

249 

250Adding a directory extends where Claude can read and edit files. It does not make that directory a full configuration root: most `.claude/` configuration is not discovered from additional directories, though a few types are loaded as exceptions.

251 

252The following configuration types are loaded from `--add-dir` directories:

253 

254| Configuration | Loaded from `--add-dir` |

255| :--------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |

256| [Skills](/en/skills) in `.claude/skills/` | Yes, with live reload |

257| Plugin settings in `.claude/settings.json` | `enabledPlugins` and `extraKnownMarketplaces` only |

258| [CLAUDE.md](/en/memory) files, `.claude/rules/`, and `CLAUDE.local.md` | Only when `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1` is set. `CLAUDE.local.md` additionally requires the `local` setting source, which is enabled by default |

259 

260Everything else, including subagents, commands, output styles, hooks, and other settings, is discovered only from the current working directory and its parents, your user directory at `~/.claude/`, and managed settings. To share that configuration across projects, use one of these approaches:

261 

262* **User-level configuration**: place files in `~/.claude/agents/`, `~/.claude/output-styles/`, or `~/.claude/settings.json` to make them available in every project

263* **Plugins**: package and distribute configuration as a [plugin](/en/plugins) that teams can install

264* **Launch from the config directory**: run Claude Code from the directory containing the `.claude/` configuration you want

265 

266## How permissions interact with sandboxing

267 

268Permissions and [sandboxing](/en/sandboxing) are complementary security layers:

269 

270* **Permissions** control which tools Claude Code can use and which files or domains it can access. They apply to all tools (Bash, Read, Edit, WebFetch, MCP, and others).

271* **Sandboxing** provides OS-level enforcement that restricts the Bash tool's filesystem and network access. It applies only to Bash commands and their child processes.

272 

273Use both for defense-in-depth:

274 

275* Permission deny rules block Claude from even attempting to access restricted resources

276* Sandbox restrictions prevent Bash commands from reaching resources outside defined boundaries, even if a prompt injection bypasses Claude's decision-making

277* Filesystem restrictions in the sandbox use Read and Edit deny rules, not separate sandbox configuration

278* Network restrictions combine WebFetch permission rules with the sandbox's `allowedDomains` and `deniedDomains` lists

279 

280When sandboxing is enabled with `autoAllowBashIfSandboxed: true`, which is the default, sandboxed Bash commands run without prompting even if your permissions include `ask: Bash(*)`. The sandbox boundary substitutes for the per-command prompt. Explicit deny rules still apply, and `rm` or `rmdir` commands that target `/`, your home directory, or other critical system paths still trigger a prompt. See [sandbox modes](/en/sandboxing#sandbox-modes) to change this behavior.

281 

282## Managed settings

283 

284For organizations that need centralized control over Claude Code configuration, administrators can deploy managed settings that cannot be overridden by user or project settings. These policy settings follow the same format as regular settings files and can be delivered through MDM/OS-level policies, managed settings files, or [server-managed settings](/en/server-managed-settings). See [settings files](/en/settings#settings-files) for delivery mechanisms and file locations.

285 

286### Managed-only settings

287 

288The following settings are only read from managed settings. Placing them in user or project settings files has no effect.

289 

290| Setting | Description |

291| :--------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

292| `allowedChannelPlugins` | Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Requires `channelsEnabled: true`. See [Restrict which channel plugins can run](/en/channels#restrict-which-channel-plugins-can-run) |

293| `allowManagedHooksOnly` | When `true`, only managed hooks, SDK hooks, and hooks from plugins force-enabled in managed settings `enabledPlugins` are loaded. User, project, and all other plugin hooks are blocked |

294| `allowManagedMcpServersOnly` | When `true`, only `allowedMcpServers` from managed settings are respected. `deniedMcpServers` still merges from all sources. See [Managed MCP configuration](/en/mcp#managed-mcp-configuration) |

295| `allowManagedPermissionRulesOnly` | When `true`, prevents user and project settings from defining `allow`, `ask`, or `deny` permission rules. Only rules in managed settings apply |

296| `blockedMarketplaces` | Blocklist of marketplace sources. Blocked sources are checked before downloading, so they never touch the filesystem. See [managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) |

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

298| `forceRemoteSettingsRefresh` | When `true`, blocks CLI startup until remote managed settings are freshly fetched and exits if the fetch fails. See [fail-closed enforcement](/en/server-managed-settings#enforce-fail-closed-startup) |

299| `pluginTrustMessage` | Custom message appended to the plugin trust warning shown before installation |

300| `sandbox.filesystem.allowManagedReadPathsOnly` | When `true`, only `filesystem.allowRead` paths from managed settings are respected. `denyRead` still merges from all sources |

301| `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 |

302| `strictKnownMarketplaces` | Controls which plugin marketplace sources users can add and install plugins from. See [managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) |

303| `wslInheritsWindowsSettings` | When `true` in the Windows HKLM registry key or `C:\Program Files\ClaudeCode\managed-settings.json`, WSL reads managed settings from the Windows policy chain in addition to `/etc/claude-code`. See [Settings files](/en/settings#settings-files) |

304 

305`disableBypassPermissionsMode` is typically placed in managed settings to enforce organizational policy, but it works from any scope. A user can set it in their own settings to lock themselves out of bypass mode.

306 

307<Note>

308 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).

309</Note>

310 

311## Settings precedence

312 

313Permission rules follow the same [settings precedence](/en/settings#settings-precedence) as all other Claude Code settings:

314 

3151. **Managed settings**: cannot be overridden by any other level, including command line arguments

3162. **Command line arguments**: temporary session overrides

3173. **Local project settings** (`.claude/settings.local.json`)

3184. **Shared project settings** (`.claude/settings.json`)

3195. **User settings** (`~/.claude/settings.json`)

320 

321If a tool is denied at any level, no other level can allow it. For example, a managed settings deny cannot be overridden by `--allowedTools`, and `--disallowedTools` can add restrictions beyond what managed settings define.

322 

323If a permission is allowed in user settings but denied in project settings, the project setting takes precedence and the permission is blocked.

324 

325## Example configurations

326 

327This [repository](https://github.com/anthropics/claude-code/tree/main/examples/settings) includes starter settings configurations for common deployment scenarios. Use these as starting points and adjust them to fit your needs.

328 

329## See also

330 

331* [Settings](/en/settings): complete configuration reference including the permission settings table

332* [Configure auto mode](/en/auto-mode-config): tell the auto mode classifier which infrastructure your organization trusts

333* [Sandboxing](/en/sandboxing): OS-level filesystem and network isolation for Bash commands

334* [Authentication](/en/authentication): set up user access to Claude Code

335* [Security](/en/security): security safeguards and best practices

336* [Hooks](/en/hooks-guide): automate workflows and extend permission evaluation

platforms.md +81 −0 added

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# Platforms and integrations

6 

7> Choose where to run Claude Code and what to connect it to. Compare the CLI, Desktop, VS Code, JetBrains, web, mobile, and integrations like Chrome, Slack, and CI/CD.

8 

9Claude Code runs the same underlying engine everywhere, but each surface is tuned for a different way of working. This page helps you pick the right platform for your workflow and connect the tools you already use.

10 

11## Where to run Claude Code

12 

13Choose a platform based on how you like to work and where your project lives.

14 

15| Platform | Best for | What you get |

16| :-------------------------------- | :------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

17| [CLI](/en/quickstart) | Terminal workflows, scripting, remote servers | Full feature set, [Agent SDK](/en/headless), [computer use](/en/computer-use) on macOS (Pro and Max), third-party providers |

18| [Desktop](/en/desktop) | Visual review, parallel sessions, managed setup | Diff viewer, app preview, [computer use](/en/desktop#let-claude-use-your-computer) and [Dispatch](/en/desktop#sessions-from-dispatch) on Pro and Max |

19| [VS Code](/en/vs-code) | Working inside VS Code without switching to a terminal | Inline diffs, integrated terminal, file context |

20| [JetBrains](/en/jetbrains) | Working inside IntelliJ, PyCharm, WebStorm, or other JetBrains IDEs | Diff viewer, selection sharing, terminal session |

21| [Web](/en/claude-code-on-the-web) | Long-running tasks that don't need much steering, or work that should continue when you're offline | Anthropic-managed cloud, continues after you disconnect |

22| Mobile | Starting and monitoring tasks while away from your computer | Cloud sessions from the Claude app for iOS and Android, [Remote Control](/en/remote-control) for local sessions, [Dispatch](/en/desktop#sessions-from-dispatch) to Desktop on Pro and Max |

23 

24The CLI is the most complete surface for terminal-native work: scripting, third-party providers, and the Agent SDK are CLI-only. Desktop and the IDE extensions trade some CLI-only features for visual review and tighter editor integration. The web runs in Anthropic's cloud, so tasks keep going after you disconnect. Mobile is a thin client into those same cloud sessions or into a local session via Remote Control, and can send tasks to Desktop with Dispatch.

25 

26You can mix surfaces on the same project. Configuration, project memory, and MCP servers are shared across the local surfaces.

27 

28## Connect your tools

29 

30Integrations let Claude work with services outside your codebase.

31 

32| Integration | What it does | Use it for |

33| :----------------------------------- | :------------------------------------------------- | :--------------------------------------------------------------- |

34| [Chrome](/en/chrome) | Controls your browser with your logged-in sessions | Testing web apps, filling forms, automating sites without an API |

35| [GitHub Actions](/en/github-actions) | Runs Claude in your CI pipeline | Automated PR reviews, issue triage, scheduled maintenance |

36| [GitLab CI/CD](/en/gitlab-ci-cd) | Same as GitHub Actions for GitLab | CI-driven automation on GitLab |

37| [Code Review](/en/code-review) | Reviews every PR automatically | Catching bugs before human review |

38| [Slack](/en/slack) | Responds to `@Claude` mentions in your channels | Turning bug reports into pull requests from team chat |

39 

40For integrations not listed here, [MCP servers](/en/mcp) and [connectors](/en/desktop#connect-external-tools) let you connect almost anything: Linear, Notion, Google Drive, or your own internal APIs.

41 

42## Work when you are away from your terminal

43 

44Claude Code offers several ways to work when you're not at your terminal. They differ in what triggers the work, where Claude runs, and how much you need to set up.

45 

46| | Trigger | Claude runs on | Setup | Best for |

47| :--------------------------------------------- | :--------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------ |

48| [Dispatch](/en/desktop#sessions-from-dispatch) | Message a task from the Claude mobile app | Your machine (Desktop) | [Pair the mobile app with Desktop](https://support.claude.com/en/articles/13947068) | Delegating work while you're away, minimal setup |

49| [Remote Control](/en/remote-control) | Drive a running session from [claude.ai/code](https://claude.ai/code) or the Claude mobile app | Your machine (CLI or VS Code) | Run `claude remote-control` | Steering in-progress work from another device |

50| [Channels](/en/channels) | Push events from a chat app like Telegram or Discord, or your own server | Your machine (CLI) | [Install a channel plugin](/en/channels#quickstart) or [build your own](/en/channels-reference) | Reacting to external events like CI failures or chat messages |

51| [Slack](/en/slack) | Mention `@Claude` in a team channel | Anthropic cloud | [Install the Slack app](/en/slack#setting-up-claude-code-in-slack) with [Claude Code on the web](/en/claude-code-on-the-web) enabled | PRs and reviews from team chat |

52| [Scheduled tasks](/en/scheduled-tasks) | Set a schedule | [CLI](/en/scheduled-tasks), [Desktop](/en/desktop-scheduled-tasks), or [cloud](/en/routines) | Pick a frequency | Recurring automation like daily reviews |

53 

54If you're not sure where to start, [install the CLI](/en/quickstart) and run it in a project directory. If you'd rather not use a terminal, [Desktop](/en/desktop-quickstart) gives you the same engine with a graphical interface.

55 

56## Related resources

57 

58### Platforms

59 

60* [CLI quickstart](/en/quickstart): install and run your first command in the terminal

61* [Desktop](/en/desktop): visual diff review, parallel sessions, computer use, and Dispatch

62* [VS Code](/en/vs-code): the Claude Code extension inside your editor

63* [JetBrains](/en/jetbrains): the extension for IntelliJ, PyCharm, and other JetBrains IDEs

64* [Claude Code on the web](/en/claude-code-on-the-web): cloud sessions that keep running when you disconnect

65* Mobile: the Claude app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) and [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude) for starting and monitoring tasks while away from your computer

66 

67### Integrations

68 

69* [Chrome](/en/chrome): automate browser tasks with your logged-in sessions

70* [Computer use](/en/computer-use): let Claude open apps and control your screen on macOS

71* [GitHub Actions](/en/github-actions): run Claude in your CI pipeline

72* [GitLab CI/CD](/en/gitlab-ci-cd): the same for GitLab

73* [Code Review](/en/code-review): automatic review on every pull request

74* [Slack](/en/slack): send tasks from team chat, get PRs back

75 

76### Remote access

77 

78* [Dispatch](/en/desktop#sessions-from-dispatch): message a task from your phone and it can spawn a Desktop session

79* [Remote Control](/en/remote-control): drive a running session from your phone or browser

80* [Channels](/en/channels): push events from chat apps or your own servers into a session

81* [Scheduled tasks](/en/scheduled-tasks): run prompts on a recurring schedule

plugin-dependencies.md +135 −0 added

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# Constrain plugin dependency versions

6 

7> Declare version constraints on plugin dependencies so your plugin keeps working when an upstream plugin ships a breaking change.

8 

9A plugin can depend on other plugins by listing them in `plugin.json` or in its marketplace entry. By default, a dependency tracks the latest available version, so an upstream release can change the dependency under your plugin without warning. Version constraints let you hold a dependency at a tested version range until you choose to move.

10 

11When you install a plugin that declares dependencies, Claude Code resolves and installs them automatically and lists which dependencies were added at the end of the install output. If a dependency later goes missing, `/reload-plugins` and the background plugin auto-update reinstall it, provided its marketplace is already in your configured marketplaces. Re-running `claude plugin install` on the dependent plugin, or adding a marketplace with `claude plugin marketplace add`, also resolves any outstanding missing dependencies. Dependencies from a marketplace you have not added are left unresolved.

12 

13This guide is for plugin authors who declare dependencies in `plugin.json` and for marketplace maintainers who tag releases. To install plugins that have dependencies, see [Discover and install plugins](/en/discover-plugins). For the full manifest schema, see the [Plugins reference](/en/plugins-reference).

14 

15<Note>

16 Dependency version constraints require Claude Code v2.1.110 or later.

17</Note>

18 

19## Why constrain dependency versions

20 

21Consider an internal marketplace where two teams publish plugins. The platform team maintains `secrets-vault`, an MCP server that wraps a secrets backend. The deploy team maintains `deploy-kit`, which calls `secrets-vault` to fetch credentials during deploys.

22 

23`deploy-kit` is tested against `secrets-vault` v2.1.0. Without a version constraint, the next time the platform team tags a release that renames an MCP tool, auto-update moves every engineer's `secrets-vault` to the new version and `deploy-kit` breaks.

24 

25With a version constraint, `deploy-kit` declares that it needs `secrets-vault` in the `~2.1.0` range. Engineers with `deploy-kit` installed stay on the highest matching `2.1.x` patch. The deploy team upgrades on their own schedule by publishing a new `deploy-kit` version with a wider constraint.

26 

27## Declare a dependency with a version constraint

28 

29List dependencies in the `dependencies` array of your plugin's `.claude-plugin/plugin.json`. Each entry is either a plugin name or an object with a version constraint.

30 

31The following manifest declares one unversioned dependency and one constrained dependency:

32 

33```json .claude-plugin/plugin.json theme={null}

34{

35 "name": "deploy-kit",

36 "version": "3.1.0",

37 "dependencies": [

38 "audit-logger",

39 { "name": "secrets-vault", "version": "~2.1.0" }

40 ]

41}

42```

43 

44An entry can be a bare string with only the plugin name, like `"audit-logger"` in the example above, which depends on whatever version that plugin's marketplace provides. For more control, use an object with these fields:

45 

46| Field | Type | Description |

47| :------------ | :----- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

48| `name` | string | Plugin name. Resolves within the same marketplace as the declaring plugin. Required. |

49| `version` | string | A [semver range](https://github.com/npm/node-semver#ranges) such as `~2.1.0`, `^2.0`, `>=1.4`, or `=2.1.0`. The dependency is fetched at the highest tagged version that satisfies this range. |

50| `marketplace` | string | A different marketplace to resolve `name` in. Cross-marketplace dependencies are blocked unless the target marketplace is listed in [`allowCrossMarketplaceDependenciesOn`](#depend-on-a-plugin-from-another-marketplace) in the root marketplace's `marketplace.json`. |

51 

52The `version` field accepts any expression supported by Node's `semver` package, including caret, tilde, hyphen, and comparator ranges. Pre-release versions such as `2.0.0-beta.1` are excluded unless your range opts in with a pre-release suffix like `^2.0.0-0`.

53 

54## Depend on a plugin from another marketplace

55 

56By default, Claude Code refuses to auto-install a dependency that lives in a different marketplace than the plugin declaring it. This prevents one marketplace from silently pulling in plugins from a source you have not reviewed.

57 

58To allow it, the maintainer of the root marketplace adds the target marketplace name to `allowCrossMarketplaceDependenciesOn` in `marketplace.json`. The root marketplace is the one that hosts the plugin the user is installing; only its allowlist is consulted, so trust does not chain through intermediate marketplaces.

59 

60The following `marketplace.json` allows `deploy-kit` to depend on a plugin from `acme-shared`:

61 

62```json .claude-plugin/marketplace.json theme={null}

63{

64 "name": "acme-tools",

65 "owner": { "name": "Acme" },

66 "allowCrossMarketplaceDependenciesOn": ["acme-shared"],

67 "plugins": [

68 {

69 "name": "deploy-kit",

70 "source": "./deploy-kit",

71 "dependencies": [

72 { "name": "audit-logger", "marketplace": "acme-shared" }

73 ]

74 }

75 ]

76}

77```

78 

79If the field is missing or does not include the target marketplace, install fails with a `cross-marketplace` error naming the field to set. Users can still install the dependency manually first, which satisfies the constraint without changing the allowlist.

80 

81## Tag plugin releases for version resolution

82 

83Version constraints resolve against git tags on the marketplace repository. For Claude Code to find a dependency's available versions, the upstream plugin's releases must be tagged using a specific naming convention.

84 

85Tag each release as `{plugin-name}--v{version}`, where `{version}` matches the `version` field in that commit's `plugin.json`. From the plugin directory, run:

86 

87```bash theme={null}

88claude plugin tag --push

89```

90 

91The `claude plugin tag` command derives the tag name from the plugin's manifest and the enclosing marketplace entry. Before creating the tag, it validates the plugin contents, checks that `plugin.json` and the marketplace entry agree on the version, requires a clean working tree under the plugin directory, and refuses if the tag already exists. Add `--dry-run` to see what would be tagged without creating it. Running `git tag secrets-vault--v2.1.0` directly is equivalent if you keep `plugin.json` and the marketplace entry in sync yourself.

92 

93The plugin name prefix lets one marketplace repository host multiple plugins with independent version lines. The `--v` separator is parsed as a prefix match on the full plugin name, so plugin names that contain hyphens are handled correctly.

94 

95When you install a plugin that declares `{ "name": "secrets-vault", "version": "~2.1.0" }`, Claude Code lists the marketplace's tags, filters to those starting with `secrets-vault--v`, and fetches the highest version satisfying `~2.1.0`. If no matching tag exists, the dependent plugin is disabled with an error listing the available versions.

96 

97The resolved tag's semver is recorded separately from `plugin.json`'s `version`, so constraint checks use the tag that was actually fetched even if `plugin.json` at that commit has a stale value. The cache directory name for a tag-resolved install includes a 12-character commit-SHA suffix, so if a maintainer force-moves a tag to a different commit, the next install gets a fresh cache directory instead of reusing stale content.

98 

99<Note>

100 For `npm` marketplace sources, the constraint does not control which version is fetched, since tag-based resolution applies only to git-backed sources. The constraint is still checked at load time, and the dependent plugin is disabled with `dependency-version-unsatisfied` if the installed version does not satisfy it.

101</Note>

102 

103## How constraints interact

104 

105When several installed plugins constrain the same dependency, Claude Code intersects their ranges and resolves the dependency to the highest version that satisfies all of them. The table below shows how common combinations resolve.

106 

107| Plugin A requires | Plugin B requires | Result |

108| :---------------- | :---------------- | :---------------------------------------------------------------------------------------------- |

109| `^2.0` | `>=2.1` | One install at the highest `2.x` tag at or above `2.1.0`. Both plugins load. |

110| `~2.1` | `~3.0` | Install of plugin B fails with `range-conflict`. Plugin A and the dependency stay as they were. |

111| `=2.1.0` | none | The dependency stays at `2.1.0`. Auto-update skips newer versions while plugin A is installed. |

112 

113Auto-update fetches a constrained dependency at the highest git tag that satisfies every installed plugin's range, rather than at the marketplace's latest version, so the dependency continues to receive updates within its allowed range. If no tag satisfies all ranges, the update is skipped and the skip appears in `/doctor` and the `/plugin` Errors tab, naming the constraining plugin.

114 

115When you uninstall the last plugin that constrains a dependency, the dependency is no longer held and resumes tracking its marketplace entry on the next update.

116 

117## Resolve dependency errors

118 

119Dependency problems surface in `claude plugin list`, in the `/plugin` interface, and in `/doctor`. The affected plugin is disabled until you resolve the error. The most common errors and their fixes are listed below.

120 

121| Error | Meaning | How to resolve |

122| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

123| `dependency-unsatisfied` | A declared dependency is not installed, or it is installed but disabled. | Run the `claude plugin install` command shown in the error message. If the dependency's marketplace is not yet configured, add it with `claude plugin marketplace add` and Claude Code resolves the dependency automatically. If the dependency is disabled, enable it. |

124| `range-conflict` | The version requirements for a dependency cannot be combined. The error message names the cause: no version satisfies all of the ranges, a range is not valid semver syntax, or the combined ranges are too complex to intersect. | Uninstall or update one of the conflicting plugins, fix any invalid `version` string, simplify long `\|\|` chains, or ask the upstream author to widen its constraint. |

125| `dependency-version-unsatisfied` | The installed dependency's version is outside this plugin's declared range. | Run `claude plugin install <dependency>@<marketplace>` to re-resolve the dependency against all current constraints. |

126| `no-matching-tag` | The dependency's repository has no `{name}--v*` tag satisfying the range. | Check that the upstream has tagged releases using the convention above, or relax your range. |

127 

128To check for these errors programmatically, run `claude plugin list --json` and read the `errors` field on each plugin.

129 

130## See also

131 

132* [Create plugins](/en/plugins): build plugins with skills, agents, and hooks

133* [Create and distribute a plugin marketplace](/en/plugin-marketplaces): host plugins for your team

134* [Plugins reference](/en/plugins-reference#plugin-manifest-schema): the full `plugin.json` schema

135* [Version management](/en/plugins-reference#version-management): how a plugin's own version is resolved and used as the cache key

Details

6 6 

7> Build and host plugin marketplaces to distribute Claude Code extensions across teams and communities.7> Build and host plugin marketplaces to distribute Claude Code extensions across teams and communities.

8 8 

9A plugin marketplace is a catalog that lets you distribute plugins to others. Marketplaces provide centralized discovery, version tracking, automatic updates, and support for multiple source types (git repositories, local paths, and more). This guide shows you how to create your own marketplace to share plugins with your team or community.9A **plugin marketplace** is a catalog that lets you distribute plugins to others. Marketplaces provide centralized discovery, version tracking, automatic updates, and support for multiple source types (git repositories, local paths, and more). This guide shows you how to create your own marketplace to share plugins with your team or community.

10 10 

11Looking to install plugins from an existing marketplace? See [Discover and install prebuilt plugins](/en/discover-plugins).11Looking to install plugins from an existing marketplace? See [Discover and install prebuilt plugins](/en/discover-plugins).

12 12 


14 14 

15Creating and distributing a marketplace involves:15Creating and distributing a marketplace involves:

16 16 

171. **Creating plugins**: build one or more plugins with commands, agents, hooks, MCP servers, or LSP servers. This guide assumes you already have plugins to distribute; see [Create plugins](/en/plugins) for details on how to create them.171. **Creating plugins**: build one or more plugins with skills, agents, hooks, MCP servers, or LSP servers. This guide assumes you already have plugins to distribute; see [Create plugins](/en/plugins) for details on how to create them.

182. **Creating a marketplace file**: define a `marketplace.json` that lists your plugins and where to find them (see [Create the marketplace file](#create-the-marketplace-file)).182. **Creating a marketplace file**: define a `marketplace.json` that lists your plugins and where to find them (see [Create the marketplace file](#create-the-marketplace-file)).

193. **Host the marketplace**: push to GitHub, GitLab, or another git host (see [Host and distribute marketplaces](#host-and-distribute-marketplaces)).193. **Host the marketplace**: push to GitHub, GitLab, or another git host (see [Host and distribute marketplaces](#host-and-distribute-marketplaces)).

204. **Share with users**: users add your marketplace with `/plugin marketplace add` and install individual plugins (see [Discover and install plugins](/en/discover-plugins)).204. **Share with users**: users add your marketplace with `/plugin marketplace add` and install individual plugins (see [Discover and install plugins](/en/discover-plugins)).


23 23 

24## Walkthrough: create a local marketplace24## Walkthrough: create a local marketplace

25 25 

26This example creates a marketplace with one plugin: a `/review` skill for code reviews. You'll create the directory structure, add a skill, create the plugin manifest and marketplace catalog, then install and test it.26This example creates a marketplace with one plugin: a `/quality-review` skill for code reviews. You'll create the directory structure, add a skill, create the plugin manifest and marketplace catalog, then install and test it.

27 27 

28<Steps>28<Steps>

29 <Step title="Create the directory structure">29 <Step title="Create the directory structure">

30 ```bash theme={null}30 ```bash theme={null}

31 mkdir -p my-marketplace/.claude-plugin31 mkdir -p my-marketplace/.claude-plugin

32 mkdir -p my-marketplace/plugins/review-plugin/.claude-plugin32 mkdir -p my-marketplace/plugins/quality-review-plugin/.claude-plugin

33 mkdir -p my-marketplace/plugins/review-plugin/skills/review33 mkdir -p my-marketplace/plugins/quality-review-plugin/skills/quality-review

34 ```34 ```

35 </Step>35 </Step>

36 36 

37 <Step title="Create the skill">37 <Step title="Create the skill">

38 Create a `SKILL.md` file that defines what the `/review` skill does.38 Create a `SKILL.md` file that defines what the `/quality-review` skill does.

39 39 

40 ```markdown my-marketplace/plugins/review-plugin/skills/review/SKILL.md theme={null}40 ```markdown my-marketplace/plugins/quality-review-plugin/skills/quality-review/SKILL.md theme={null}

41 ---41 ---

42 description: Review code for bugs, security, and performance42 description: Review code for bugs, security, and performance

43 disable-model-invocation: true43 disable-model-invocation: true


56 <Step title="Create the plugin manifest">56 <Step title="Create the plugin manifest">

57 Create a `plugin.json` file that describes the plugin. The manifest goes in the `.claude-plugin/` directory.57 Create a `plugin.json` file that describes the plugin. The manifest goes in the `.claude-plugin/` directory.

58 58 

59 ```json my-marketplace/plugins/review-plugin/.claude-plugin/plugin.json theme={null}59 ```json my-marketplace/plugins/quality-review-plugin/.claude-plugin/plugin.json theme={null}

60 {60 {

61 "name": "review-plugin",61 "name": "quality-review-plugin",

62 "description": "Adds a /review skill for quick code reviews",62 "description": "Adds a /quality-review skill for quick code reviews",

63 "version": "1.0.0"63 "version": "1.0.0"

64 }64 }

65 ```65 ```

66 

67 <Note>

68 Setting `version` means users only receive updates when you change this field, so bump it on every release. If you omit `version` and host this marketplace in git, every commit automatically counts as a new version. See [Version resolution](#version-resolution-and-release-channels) to choose the right approach.

69 </Note>

66 </Step>70 </Step>

67 71 

68 <Step title="Create the marketplace file">72 <Step title="Create the marketplace file">


76 },80 },

77 "plugins": [81 "plugins": [

78 {82 {

79 "name": "review-plugin",83 "name": "quality-review-plugin",

80 "source": "./plugins/review-plugin",84 "source": "./plugins/quality-review-plugin",

81 "description": "Adds a /review skill for quick code reviews"85 "description": "Adds a /quality-review skill for quick code reviews"

82 }86 }

83 ]87 ]

84 }88 }


90 94 

91 ```shell theme={null}95 ```shell theme={null}

92 /plugin marketplace add ./my-marketplace96 /plugin marketplace add ./my-marketplace

93 /plugin install review-plugin@my-plugins97 /plugin install quality-review-plugin@my-plugins

94 ```98 ```

95 </Step>99 </Step>

96 100 

97 <Step title="Try it out">101 <Step title="Try it out">

98 Select some code in your editor and run your new command.102 Select some code in your editor and run your new skill.

99 103 

100 ```shell theme={null}104 ```shell theme={null}

101 /review105 /quality-review

102 ```106 ```

103 </Step>107 </Step>

104</Steps>108</Steps>


108<Note>112<Note>

109 **How plugins are installed**: When users install a plugin, Claude Code copies the plugin directory to a cache location. This means plugins can't reference files outside their directory using paths like `../shared-utils`, because those files won't be copied.113 **How plugins are installed**: When users install a plugin, Claude Code copies the plugin directory to a cache location. This means plugins can't reference files outside their directory using paths like `../shared-utils`, because those files won't be copied.

110 114 

111 If you need to share files across plugins, use symlinks (which are followed during copying) or restructure your marketplace so the shared directory is inside the plugin source path. See [Plugin caching and file resolution](/en/plugins-reference#plugin-caching-and-file-resolution) for details.115 If you need to share files across plugins, use symlinks. See [Plugin caching and file resolution](/en/plugins-reference#plugin-caching-and-file-resolution) for details.

112</Note>116</Note>

113 117 

114## Create the marketplace file118## Create the marketplace file


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

158 162 

159<Note>163<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.164 **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>165</Note>

162 166 

163### Owner fields167### Owner fields


167| `name` | string | Yes | Name of the maintainer or team |171| `name` | string | Yes | Name of the maintainer or team |

168| `email` | string | No | Contact email for the maintainer |172| `email` | string | No | Contact email for the maintainer |

169 173 

170### Optional metadata174### Optional fields

171 175 

172| Field | Type | Description |176| Field | Type | Description |

173| :--------------------- | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |177| :------------------------------------ | :----- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

174| `metadata.description` | string | Brief marketplace description |178| `metadata.description` | string | Brief marketplace description |

175| `metadata.version` | string | Marketplace version |179| `metadata.version` | string | Marketplace version |

176| `metadata.pluginRoot` | string | Base directory prepended to relative plugin source paths (for example, `"./plugins"` lets you write `"source": "formatter"` instead of `"source": "./plugins/formatter"`) |180| `metadata.pluginRoot` | string | Base directory prepended to relative plugin source paths (for example, `"./plugins"` lets you write `"source": "formatter"` instead of `"source": "./plugins/formatter"`) |

181| `allowCrossMarketplaceDependenciesOn` | array | Other marketplaces that plugins in this marketplace may depend on. Dependencies from a marketplace not listed here are blocked at install. See [Depend on a plugin from another marketplace](/en/plugin-dependencies#depend-on-a-plugin-from-another-marketplace). |

177 182 

178## Plugin entries183## Plugin entries

179 184 


191**Standard metadata fields:**196**Standard metadata fields:**

192 197 

193| Field | Type | Description |198| Field | Type | Description |

194| :------------ | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |199| :------------ | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

195| `description` | string | Brief plugin description |200| `description` | string | Brief plugin description |

196| `version` | string | Plugin version |201| `version` | string | Plugin version. If set (here or in `plugin.json`), the plugin is pinned to this string and users only receive updates when it changes. Omit to fall back to the git commit SHA. See [Version resolution](#version-resolution-and-release-channels). |

197| `author` | object | Plugin author information (`name` required, `email` optional) |202| `author` | object | Plugin author information (`name` required, `email` optional) |

198| `homepage` | string | Plugin homepage or documentation URL |203| `homepage` | string | Plugin homepage or documentation URL |

199| `repository` | string | Source code repository URL |204| `repository` | string | Source code repository URL |


201| `keywords` | array | Tags for plugin discovery and categorization |206| `keywords` | array | Tags for plugin discovery and categorization |

202| `category` | string | Plugin category for organization |207| `category` | string | Plugin category for organization |

203| `tags` | array | Tags for searchability |208| `tags` | array | Tags for searchability |

204| `strict` | boolean | Controls whether plugins need their own `plugin.json` file. When `true` (default), the plugin source must contain a `plugin.json`, and any fields you add here in the marketplace entry get merged with it. When `false`, the plugin doesn't need its own `plugin.json`; the marketplace entry itself defines everything about the plugin. Use `false` when you want to define simple plugins entirely in your marketplace file. |209| `strict` | boolean | Controls whether `plugin.json` is the authority for component definitions (default: true). See [Strict mode](#strict-mode) below. |

205 210 

206**Component configuration fields:**211**Component configuration fields:**

207 212 

208| Field | Type | Description |213| Field | Type | Description |

209| :----------- | :------------- | :----------------------------------------------- |214| :----------- | :------------- | :------------------------------------------------------------- |

210| `commands` | string\|array | Custom paths to command files or directories |215| `skills` | string\|array | Custom paths to skill directories containing `<name>/SKILL.md` |

216| `commands` | string\|array | Custom paths to flat `.md` skill files or directories |

211| `agents` | string\|array | Custom paths to agent files |217| `agents` | string\|array | Custom paths to agent files |

212| `hooks` | string\|object | Custom hooks configuration or path to hooks file |218| `hooks` | string\|object | Custom hooks configuration or path to hooks file |

213| `mcpServers` | string\|object | MCP server configurations or path to MCP config |219| `mcpServers` | string\|object | MCP server configurations or path to MCP config |


215 221 

216## Plugin sources222## Plugin sources

217 223 

224Plugin sources tell Claude Code where to fetch each individual plugin listed in your marketplace. These are set in the `source` field of each plugin entry in `marketplace.json`.

225 

226Once a plugin is cloned or copied into the local machine, it is copied into the local versioned plugin cache at `~/.claude/plugins/cache`.

227 

228| Source | Type | Fields | Notes |

229| ------------- | ------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |

230| Relative path | `string` (e.g. `"./my-plugin"`) | none | Local directory within the marketplace repo. Must start with `./`. Resolved relative to the marketplace root, not the `.claude-plugin/` directory |

231| `github` | object | `repo`, `ref?`, `sha?` | |

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

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

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

235 

236<Note>

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

238 

239 * **Marketplace source** — where to fetch the `marketplace.json` catalog itself. Set when users run `/plugin marketplace add` or in `extraKnownMarketplaces` settings. Supports `ref` (branch/tag) but not `sha`.

240 * **Plugin source** — where to fetch an individual plugin listed in the marketplace. Set in the `source` field of each plugin entry inside `marketplace.json`. Supports both `ref` (branch/tag) and `sha` (exact commit).

241 

242 For example, a marketplace hosted at `acme-corp/plugin-catalog` (marketplace source) can list a plugin fetched from `acme-corp/code-formatter` (plugin source). The marketplace source and plugin source point to different repositories and are pinned independently.

243</Note>

244 

218### Relative paths245### Relative paths

219 246 

220For plugins in the same repository:247For plugins in the same repository, use a path starting with `./`:

221 248 

222```json theme={null}249```json theme={null}

223{250{


226}253}

227```254```

228 255 

256Paths resolve relative to the marketplace root, which is the directory containing `.claude-plugin/`. In the example above, `./plugins/my-plugin` points to `<repo>/plugins/my-plugin`, even though `marketplace.json` lives at `<repo>/.claude-plugin/marketplace.json`. Do not use `../` to reference paths outside the marketplace root.

257 

229<Note>258<Note>

230 Relative paths only work when users add your marketplace via Git (GitHub, GitLab, or git URL). If users add your marketplace via a direct URL to the `marketplace.json` file, relative paths will not resolve correctly. For URL-based distribution, use GitHub, npm, or git URL sources instead. See [Troubleshooting](#plugins-with-relative-paths-fail-in-url-based-marketplaces) for details.259 Relative paths only work when users add your marketplace via Git (GitHub, GitLab, or git URL). If users add your marketplace via a direct URL to the `marketplace.json` file, relative paths will not resolve correctly. For URL-based distribution, use GitHub, npm, or git URL sources instead. See [Troubleshooting](#plugins-with-relative-paths-fail-in-url-based-marketplaces) for details.

231</Note>260</Note>


289```318```

290 319 

291| Field | Type | Description |320| Field | Type | Description |

292| :---- | :----- | :-------------------------------------------------------------------- |321| :---- | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------- |

293| `url` | string | Required. Full git repository URL (must end with `.git`) |322| `url` | string | Required. Full git repository URL (`https://` or `git@`). The `.git` suffix is optional, so Azure DevOps and AWS CodeCommit URLs without the suffix work |

294| `ref` | string | Optional. Git branch or tag (defaults to repository default branch) |323| `ref` | string | Optional. Git branch or tag (defaults to repository default branch) |

295| `sha` | string | Optional. Full 40-character git commit SHA to pin to an exact version |324| `sha` | string | Optional. Full 40-character git commit SHA to pin to an exact version |

296 325 

326### Git subdirectories

327 

328Use `git-subdir` to point to a plugin that lives inside a subdirectory of a git repository. Claude Code uses a sparse, partial clone to fetch only the subdirectory, minimizing bandwidth for large monorepos.

329 

330```json theme={null}

331{

332 "name": "my-plugin",

333 "source": {

334 "source": "git-subdir",

335 "url": "https://github.com/acme-corp/monorepo.git",

336 "path": "tools/claude-plugin"

337 }

338}

339```

340 

341You can pin to a specific branch, tag, or commit:

342 

343```json theme={null}

344{

345 "name": "my-plugin",

346 "source": {

347 "source": "git-subdir",

348 "url": "https://github.com/acme-corp/monorepo.git",

349 "path": "tools/claude-plugin",

350 "ref": "v2.0.0",

351 "sha": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"

352 }

353}

354```

355 

356The `url` field also accepts a GitHub shorthand (`owner/repo`) or SSH URLs (`git@github.com:owner/repo.git`).

357 

358| Field | Type | Description |

359| :----- | :----- | :------------------------------------------------------------------------------------------------------- |

360| `url` | string | Required. Git repository URL, GitHub `owner/repo` shorthand, or SSH URL |

361| `path` | string | Required. Subdirectory path within the repo containing the plugin (for example, `"tools/claude-plugin"`) |

362| `ref` | string | Optional. Git branch or tag (defaults to repository default branch) |

363| `sha` | string | Optional. Full 40-character git commit SHA to pin to an exact version |

364 

365### npm packages

366 

367Plugins distributed as npm packages are installed using `npm install`. This works with any package on the public npm registry or a private registry your team hosts.

368 

369```json theme={null}

370{

371 "name": "my-npm-plugin",

372 "source": {

373 "source": "npm",

374 "package": "@acme/claude-plugin"

375 }

376}

377```

378 

379To pin to a specific version, add the `version` field:

380 

381```json theme={null}

382{

383 "name": "my-npm-plugin",

384 "source": {

385 "source": "npm",

386 "package": "@acme/claude-plugin",

387 "version": "2.1.0"

388 }

389}

390```

391 

392To install from a private or internal registry, add the `registry` field:

393 

394```json theme={null}

395{

396 "name": "my-npm-plugin",

397 "source": {

398 "source": "npm",

399 "package": "@acme/claude-plugin",

400 "version": "^2.0.0",

401 "registry": "https://npm.example.com"

402 }

403}

404```

405 

406| Field | Type | Description |

407| :--------- | :----- | :------------------------------------------------------------------------------------------- |

408| `package` | string | Required. Package name or scoped package (for example, `@org/plugin`) |

409| `version` | string | Optional. Version or version range (for example, `2.1.0`, `^2.0.0`, `~1.5.0`) |

410| `registry` | string | Optional. Custom npm registry URL. Defaults to the system npm registry (typically npmjs.org) |

411 

297### Advanced plugin entries412### Advanced plugin entries

298 413 

299This example shows a plugin entry using many of the optional fields, including custom paths for commands, agents, hooks, and MCP servers:414This example shows a plugin entry using many of the optional fields, including custom paths for commands, agents, hooks, and MCP servers:


348Key things to notice:463Key things to notice:

349 464 

350* **`commands` and `agents`**: You can specify multiple directories or individual files. Paths are relative to the plugin root.465* **`commands` and `agents`**: You can specify multiple directories or individual files. Paths are relative to the plugin root.

351* **`${CLAUDE_PLUGIN_ROOT}`**: Use this variable in hooks and MCP server configs to reference files within the plugin's installation directory. This is necessary because plugins are copied to a cache location when installed.466* **`${CLAUDE_PLUGIN_ROOT}`**: use this variable in hooks and MCP server configs to reference files within the plugin's installation directory. This is necessary because plugins are copied to a cache location when installed. For dependencies or state that should survive plugin updates, use [`${CLAUDE_PLUGIN_DATA}`](/en/plugins-reference#persistent-data-directory) instead.

352* **`strict: false`**: Since this is set to false, the plugin doesn't need its own `plugin.json`. The marketplace entry defines everything.467* **`strict: false`**: Since this is set to false, the plugin doesn't need its own `plugin.json`. The marketplace entry defines everything. See [Strict mode](#strict-mode) below.

468 

469### Strict mode

470 

471The `strict` field controls whether `plugin.json` is the authority for component definitions (skills, agents, hooks, MCP servers, output styles).

472 

473| Value | Behavior |

474| :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |

475| `true` (default) | `plugin.json` is the authority. The marketplace entry can supplement it with additional components, and both sources are merged. |

476| `false` | The marketplace entry is the entire definition. If the plugin also has a `plugin.json` that declares components, that's a conflict and the plugin fails to load. |

477 

478**When to use each mode:**

479 

480* **`strict: true`**: the plugin has its own `plugin.json` and manages its own components. The marketplace entry can add extra skills or hooks on top. This is the default and works for most plugins.

481* **`strict: false`**: the marketplace operator wants full control. The plugin repo provides raw files, and the marketplace entry defines which of those files are exposed as skills, agents, hooks, etc. Useful when the marketplace restructures or curates a plugin's components differently than the plugin author intended.

353 482 

354## Host and distribute marketplaces483## Host and distribute marketplaces

355 484 


373 502 

374### Private repositories503### Private repositories

375 504 

376Claude Code supports installing plugins from private repositories. For manual installation and updates, Claude Code uses your existing git credential helpers. If `git clone` works for a private repository in your terminal, it works in Claude Code too. Common credential helpers include `gh auth login` for GitHub, macOS Keychain, and `git-credential-store`.505Claude Code supports installing plugins from private repositories. For manual installation and updates, Claude Code uses your existing git credential helpers, so HTTPS access via `gh auth login`, macOS Keychain, or `git-credential-store` works the same as in your terminal. SSH access works as long as the host is already in your `known_hosts` file and the key is loaded in `ssh-agent`, since Claude Code suppresses interactive SSH prompts for the host fingerprint and key passphrase.

377 506 

378Background auto-updates run at startup without credential helpers, since interactive prompts would block Claude Code from starting. To enable auto-updates for private marketplaces, set the appropriate authentication token in your environment:507Background auto-updates run at startup without credential helpers, since interactive prompts would block Claude Code from starting. To enable auto-updates for private marketplaces, set the appropriate authentication token in your environment:

379 508 


434 563 

435For full configuration options, see [Plugin settings](/en/settings#plugin-settings).564For full configuration options, see [Plugin settings](/en/settings#plugin-settings).

436 565 

566<Note>

567 If you use a local `directory` or `file` source with a relative path, the path resolves against your repository's main checkout. When you run Claude Code from a git worktree, the path still points at the main checkout, so all worktrees share the same marketplace location. Marketplace state is stored once per user in `~/.claude/plugins/known_marketplaces.json`, not per project.

568</Note>

569 

570### Pre-populate plugins for containers

571 

572For container images and CI environments, you can pre-populate a plugins directory at build time so Claude Code starts with marketplaces and plugins already available, without cloning anything at runtime. Set the `CLAUDE_CODE_PLUGIN_SEED_DIR` environment variable to point at this directory.

573 

574To layer multiple seed directories, separate paths with `:` on Unix or `;` on Windows. Claude Code searches each directory in order, and the first seed that contains a given marketplace or plugin cache wins.

575 

576The seed directory mirrors the structure of `~/.claude/plugins`:

577 

578```

579$CLAUDE_CODE_PLUGIN_SEED_DIR/

580 known_marketplaces.json

581 marketplaces/<name>/...

582 cache/<marketplace>/<plugin>/<version>/...

583```

584 

585To build a seed directory, run Claude Code once during image build, install the plugins you need, then copy the resulting `~/.claude/plugins` directory into your image and point `CLAUDE_CODE_PLUGIN_SEED_DIR` at it.

586 

587To skip the copy step, set `CLAUDE_CODE_PLUGIN_CACHE_DIR` to your target seed path during the build so plugins install directly there:

588 

589```bash theme={null}

590CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed claude plugin marketplace add your-org/plugins

591CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed claude plugin install my-tool@your-plugins

592```

593 

594Then set `CLAUDE_CODE_PLUGIN_SEED_DIR=/opt/claude-seed` in your container's runtime environment so Claude Code reads from the seed on startup.

595 

596At startup, Claude Code registers marketplaces found in the seed's `known_marketplaces.json` into the primary configuration, and uses plugin caches found under `cache/` in place without re-cloning. This works in both interactive mode and non-interactive mode with the `-p` flag.

597 

598Behavior details:

599 

600* **Read-only**: the seed directory is never written to. Auto-updates are disabled for seed marketplaces since git pull would fail on a read-only filesystem.

601* **Seed entries take precedence**: marketplaces declared in the seed overwrite any matching entries in the user's configuration on each startup. To opt out of a seed plugin, use `/plugin disable` rather than removing the marketplace.

602* **Path resolution**: Claude Code locates marketplace content by probing `$CLAUDE_CODE_PLUGIN_SEED_DIR/marketplaces/<name>/` at runtime, not by trusting paths stored inside the seed's JSON. This means the seed works correctly even when mounted at a different path than where it was built.

603* **Mutation is blocked**: running `/plugin marketplace remove` or `/plugin marketplace update` against a seed-managed marketplace fails with guidance to ask your administrator to update the seed image.

604* **Composes with settings**: if `extraKnownMarketplaces` or `enabledPlugins` declare a marketplace that already exists in the seed, Claude Code uses the seed copy instead of cloning.

605 

437### Managed marketplace restrictions606### Managed marketplace restrictions

438 607 

439For organizations requiring strict control over plugin sources, administrators can restrict which plugin marketplaces users are allowed to add using the [`strictKnownMarketplaces`](/en/settings#strictknownmarketplaces) setting in managed settings.608For organizations requiring strict control over plugin sources, administrators can restrict which plugin marketplaces users are allowed to add using the [`strictKnownMarketplaces`](/en/settings#strictknownmarketplaces) setting in managed settings.


478}647}

479```648```

480 649 

481Allow all marketplaces from an internal git server using regex pattern matching:650Allow all marketplaces from an internal git server using regex pattern matching on the host. This is the recommended approach for [GitHub Enterprise Server](/en/github-enterprise-server#plugin-marketplaces-on-ghes) or self-hosted GitLab instances:

482 651 

483```json theme={null}652```json theme={null}

484{653{


491}660}

492```661```

493 662 

663Allow filesystem-based marketplaces from a specific directory using regex pattern matching on the path:

664 

665```json theme={null}

666{

667 "strictKnownMarketplaces": [

668 {

669 "source": "pathPattern",

670 "pathPattern": "^/opt/approved/"

671 }

672 ]

673}

674```

675 

676Use `".*"` as the `pathPattern` to allow any filesystem path while still controlling network sources with `hostPattern`.

677 

678<Note>

679 `strictKnownMarketplaces` restricts what users can add, but does not register marketplaces on its own. To make allowed marketplaces available automatically without users running `/plugin marketplace add`, pair it with [`extraKnownMarketplaces`](/en/settings#extraknownmarketplaces) in the same `managed-settings.json`. See [Using both together](/en/settings#strictknownmarketplaces).

680</Note>

681 

494#### How restrictions work682#### How restrictions work

495 683 

496Restrictions are validated early in the plugin installation process, before any network requests or filesystem operations occur. This prevents unauthorized marketplace access attempts.684Restrictions are checked before any network or filesystem operation. The check runs on marketplace add and on plugin install, update, refresh, and auto-update. If a marketplace was added before the policy was configured and its source no longer matches the allowlist, Claude Code refuses to install or update plugins from it. The same enforcement applies to `blockedMarketplaces`.

497 685 

498The allowlist uses exact matching for most source types. For a marketplace to be allowed, all specified fields must match exactly:686The allowlist uses exact matching for most source types. For a marketplace to be allowed, all specified fields must match exactly:

499 687 

500* For GitHub sources: `repo` is required, and `ref` or `path` must also match if specified in the allowlist688* For GitHub sources: `repo` is required, and `ref` or `path` must also match if specified in the allowlist

501* For URL sources: the full URL must match exactly689* For URL sources: the full URL must match exactly

502* For `hostPattern` sources: the marketplace host is matched against the regex pattern690* For `hostPattern` sources: the marketplace host is matched against the regex pattern

691* For `pathPattern` sources: the marketplace's filesystem path is matched against the regex pattern

503 692 

504Because `strictKnownMarketplaces` is set in [managed settings](/en/settings#settings-files), individual users and project configurations cannot override these restrictions.693Because `strictKnownMarketplaces` is set in [managed settings](/en/settings#settings-files), individual users and project configurations cannot override these restrictions.

505 694 

506For complete configuration details including all supported source types and comparison with `extraKnownMarketplaces`, see the [strictKnownMarketplaces reference](/en/settings#strictknownmarketplaces).695For complete configuration details including all supported source types and comparison with `extraKnownMarketplaces`, see the [strictKnownMarketplaces reference](/en/settings#strictknownmarketplaces).

507 696 

697### Version resolution and release channels

698 

699Plugin versions determine cache paths and update detection: if the resolved version matches what a user already has, `/plugin update` and auto-update skip the plugin.

700 

701Claude Code resolves a plugin's version from the first of these that is set:

702 

7031. `version` in the plugin's `plugin.json`

7042. `version` in the plugin's marketplace entry

7053. The git commit SHA of the plugin's source

706 

707For the git-based source types `github`, `url`, `git-subdir`, and relative paths inside a git-hosted marketplace, you can omit `version` entirely and every new commit is treated as a new version. This is the simplest setup for internal or actively-developed plugins.

708 

709<Warning>

710 Setting `version` pins the plugin. If `plugin.json` declares `"version": "1.0.0"`, pushing new commits without changing that string does nothing for existing users, because Claude Code sees the same version and keeps the cached copy. Bump the field on every release, or omit it to use the commit SHA.

711 

712 Avoid setting `version` in both `plugin.json` and the marketplace entry. The `plugin.json` value always wins silently, so a stale manifest version can mask a version you set in `marketplace.json`.

713</Warning>

714 

715#### Set up release channels

716 

717To support "stable" and "latest" release channels for your plugins, you can set up two marketplaces that point to different refs or SHAs of the same repo. You can then assign the two marketplaces to different user groups through [managed settings](/en/settings#settings-files).

718 

719<Warning>

720 Each channel must resolve to a different version. If you use explicit versions, `plugin.json` must declare a different `version` at each pinned ref. If you omit `version`, the distinct commit SHAs already distinguish the channels. If two refs resolve to the same version string, Claude Code treats them as identical and skips the update.

721</Warning>

722 

723##### Example

724 

725```json theme={null}

726{

727 "name": "stable-tools",

728 "plugins": [

729 {

730 "name": "code-formatter",

731 "source": {

732 "source": "github",

733 "repo": "acme-corp/code-formatter",

734 "ref": "stable"

735 }

736 }

737 ]

738}

739```

740 

741```json theme={null}

742{

743 "name": "latest-tools",

744 "plugins": [

745 {

746 "name": "code-formatter",

747 "source": {

748 "source": "github",

749 "repo": "acme-corp/code-formatter",

750 "ref": "latest"

751 }

752 }

753 ]

754}

755```

756 

757##### Assign channels to user groups

758 

759Assign each marketplace to the appropriate user group through managed settings. For example, the stable group receives:

760 

761```json theme={null}

762{

763 "extraKnownMarketplaces": {

764 "stable-tools": {

765 "source": {

766 "source": "github",

767 "repo": "acme-corp/stable-tools"

768 }

769 }

770 }

771}

772```

773 

774The early-access group receives `latest-tools` instead:

775 

776```json theme={null}

777{

778 "extraKnownMarketplaces": {

779 "latest-tools": {

780 "source": {

781 "source": "github",

782 "repo": "acme-corp/latest-tools"

783 }

784 }

785 }

786}

787```

788 

789#### Pin dependency versions

790 

791A plugin can constrain its dependencies to a semver range so that updates to a dependency do not break the dependent plugin. See [Constrain plugin dependency versions](/en/plugin-dependencies) for the `{plugin-name}--v{version}` git-tag convention, range syntax, and how multiple constraints on the same dependency are combined.

792 

508## Validation and testing793## Validation and testing

509 794 

510Test your marketplace before sharing.795Test your marketplace before sharing.


535 820 

536For complete plugin testing workflows, see [Test your plugins locally](/en/plugins#test-your-plugins-locally). For technical troubleshooting, see [Plugins reference](/en/plugins-reference).821For complete plugin testing workflows, see [Test your plugins locally](/en/plugins#test-your-plugins-locally). For technical troubleshooting, see [Plugins reference](/en/plugins-reference).

537 822 

823## Manage marketplaces from the CLI

824 

825Claude Code provides non-interactive `claude plugin marketplace` subcommands for scripting and automation. These are equivalent to the `/plugin marketplace` commands available inside an interactive session.

826 

827### Plugin marketplace add

828 

829Add a marketplace from a GitHub repository, git URL, remote URL, or local path.

830 

831```bash theme={null}

832claude plugin marketplace add <source> [options]

833```

834 

835**Arguments:**

836 

837* `<source>`: GitHub `owner/repo` shorthand, git URL, remote URL to a `marketplace.json` file, or local directory path. To pin to a branch or tag, append `@ref` to the GitHub shorthand or `#ref` to a git URL

838 

839**Options:**

840 

841| Option | Description | Default |

842| :-------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | :------ |

843| `--scope <scope>` | Where to declare the marketplace: `user`, `project`, or `local`. See [Plugin installation scopes](/en/plugins-reference#plugin-installation-scopes) | `user` |

844| `--sparse <paths...>` | Limit checkout to specific directories via git sparse-checkout. Useful for monorepos | |

845 

846Add a marketplace from GitHub using `owner/repo` shorthand:

847 

848```bash theme={null}

849claude plugin marketplace add acme-corp/claude-plugins

850```

851 

852Pin to a specific branch or tag with `@ref`:

853 

854```bash theme={null}

855claude plugin marketplace add acme-corp/claude-plugins@v2.0

856```

857 

858Add from a git URL on a non-GitHub host:

859 

860```bash theme={null}

861claude plugin marketplace add https://gitlab.example.com/team/plugins.git

862```

863 

864Add from a remote URL that serves the `marketplace.json` file directly:

865 

866```bash theme={null}

867claude plugin marketplace add https://example.com/marketplace.json

868```

869 

870Add from a local directory for testing:

871 

872```bash theme={null}

873claude plugin marketplace add ./my-marketplace

874```

875 

876Declare the marketplace at project scope so it is shared with your team via `.claude/settings.json`:

877 

878```bash theme={null}

879claude plugin marketplace add acme-corp/claude-plugins --scope project

880```

881 

882For a monorepo, limit the checkout to the directories that contain plugin content:

883 

884```bash theme={null}

885claude plugin marketplace add acme-corp/monorepo --sparse .claude-plugin plugins

886```

887 

888### Plugin marketplace list

889 

890List all configured marketplaces.

891 

892```bash theme={null}

893claude plugin marketplace list [options]

894```

895 

896**Options:**

897 

898| Option | Description |

899| :------- | :------------- |

900| `--json` | Output as JSON |

901 

902### Plugin marketplace remove

903 

904Remove a configured marketplace. The alias `rm` is also accepted.

905 

906```bash theme={null}

907claude plugin marketplace remove <name>

908```

909 

910**Arguments:**

911 

912* `<name>`: marketplace name to remove, as shown by `claude plugin marketplace list`. This is the `name` from `marketplace.json`, not the source you passed to `add`

913 

914<Warning>

915 Removing a marketplace also uninstalls any plugins you installed from it. To refresh a marketplace without losing installed plugins, use `claude plugin marketplace update` instead.

916</Warning>

917 

918### Plugin marketplace update

919 

920Refresh marketplaces from their sources to retrieve new plugins and version changes.

921 

922```bash theme={null}

923claude plugin marketplace update [name]

924```

925 

926**Arguments:**

927 

928* `[name]`: marketplace name to update, as shown by `claude plugin marketplace list`. Updates all marketplaces if omitted

929 

930Both `remove` and `update` fail when run against a seed-managed marketplace, which is read-only. When updating all marketplaces, seed-managed entries are skipped and other marketplaces still update. To change seed-provided plugins, ask your administrator to update the seed image. See [Pre-populate plugins for containers](#pre-populate-plugins-for-containers).

931 

538## Troubleshooting932## Troubleshooting

539 933 

540### Marketplace not loading934### Marketplace not loading


545 939 

546* Verify the marketplace URL is accessible940* Verify the marketplace URL is accessible

547* Check that `.claude-plugin/marketplace.json` exists at the specified path941* Check that `.claude-plugin/marketplace.json` exists at the specified path

548* Ensure JSON syntax is valid using `claude plugin validate` or `/plugin validate`942* Ensure JSON syntax is valid and frontmatter is well-formed using `claude plugin validate` or `/plugin validate`

549* For private repositories, confirm you have access permissions943* For private repositories, confirm you have access permissions

550 944 

551### Marketplace validation errors945### Marketplace validation errors

552 946 

553Run `claude plugin validate .` or `/plugin validate .` from your marketplace directory to check for issues. Common errors:947Run `claude plugin validate .` or `/plugin validate .` from your marketplace directory to check for issues. The validator checks `plugin.json`, skill/agent/command frontmatter, and `hooks/hooks.json` for syntax and schema errors. Common errors:

554 948 

555| Error | Cause | Solution |949| Error | Cause | Solution |

556| :------------------------------------------------ | :------------------------------ | :------------------------------------------------------------ |950| :------------------------------------------------ | :---------------------------------------------- | :--------------------------------------------------------------------------------------------- |

557| `File not found: .claude-plugin/marketplace.json` | Missing manifest | Create `.claude-plugin/marketplace.json` with required fields |951| `File not found: .claude-plugin/marketplace.json` | Missing manifest | Create `.claude-plugin/marketplace.json` with required fields |

558| `Invalid JSON syntax: Unexpected token...` | JSON syntax error | Check for missing commas, extra commas, or unquoted strings |952| `Invalid JSON syntax: Unexpected token...` | JSON syntax error in marketplace.json | Check for missing commas, extra commas, or unquoted strings |

559| `Duplicate plugin name "x" found in marketplace` | Two plugins share the same name | Give each plugin a unique `name` value |953| `Duplicate plugin name "x" found in marketplace` | Two plugins share the same name | Give each plugin a unique `name` value |

560| `plugins[0].source: Path traversal not allowed` | Source path contains `..` | Use paths relative to marketplace root without `..` |954| `plugins[0].source: Path contains ".."` | Source path contains `..` | Use paths relative to the marketplace root without `..`. See [Relative paths](#relative-paths) |

955| `YAML frontmatter failed to parse: ...` | Invalid YAML in a skill, agent, or command file | Fix the YAML syntax in the frontmatter block. At runtime this file loads with no metadata. |

956| `Invalid JSON syntax: ...` (hooks.json) | Malformed `hooks/hooks.json` | Fix JSON syntax. A malformed `hooks/hooks.json` prevents the entire plugin from loading. |

561 957 

562**Warnings** (non-blocking):958**Warnings** (non-blocking):

563 959 

564* `Marketplace has no plugins defined`: add at least one plugin to the `plugins` array960* `Marketplace has no plugins defined`: add at least one plugin to the `plugins` array

565* `No marketplace description provided`: add `metadata.description` to help users understand your marketplace961* `No marketplace description provided`: add `metadata.description` to help users understand your marketplace

566* `Plugin "x" uses npm source which is not yet fully implemented`: use `github` or local path sources instead962* `Plugin name "x" is not kebab-case`: the plugin name contains uppercase letters, spaces, or special characters. Rename to lowercase letters, digits, and hyphens only (for example, `my-plugin`). Claude Code accepts other forms, but the Claude.ai marketplace sync rejects them.

567 963 

568### Plugin installation failures964### Plugin installation failures

569 965 


596* For GitLab, ensure the token has at least `read_repository` scope992* For GitLab, ensure the token has at least `read_repository` scope

597* Verify the token hasn't expired993* Verify the token hasn't expired

598 994 

995### Marketplace updates fail in offline environments

996 

997**Symptoms**: Marketplace `git pull` fails and Claude Code wipes the existing cache, causing plugins to become unavailable.

998 

999**Cause**: By default, when a `git pull` fails, Claude Code removes the stale clone and attempts to re-clone. In offline or airgapped environments, re-cloning fails the same way, leaving the marketplace directory empty.

1000 

1001**Solution**: Set `CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE=1` to keep the existing cache when the pull fails instead of wiping it:

1002 

1003```bash theme={null}

1004export CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE=1

1005```

1006 

1007With this variable set, Claude Code retains the stale marketplace clone on `git pull` failure and continues using the last-known-good state. For fully offline deployments where the repository will never be reachable, use [`CLAUDE_CODE_PLUGIN_SEED_DIR`](#pre-populate-plugins-for-containers) to pre-populate the plugins directory at build time instead.

1008 

1009### Git operations time out

1010 

1011**Symptoms**: Plugin installation or marketplace updates fail with a timeout error like "Git clone timed out after 120s" or "Git pull timed out after 120s".

1012 

1013**Cause**: Claude Code uses a 120-second timeout for all git operations, including cloning plugin repositories and pulling marketplace updates. Large repositories or slow network connections may exceed this limit.

1014 

1015**Solution**: Increase the timeout using the `CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS` environment variable. The value is in milliseconds:

1016 

1017```bash theme={null}

1018export CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS=300000 # 5 minutes

1019```

1020 

599### Plugins with relative paths fail in URL-based marketplaces1021### Plugins with relative paths fail in URL-based marketplaces

600 1022 

601**Symptoms**: Added a marketplace via URL (such as `https://example.com/marketplace.json`), but plugins with relative path sources like `"./plugins/my-plugin"` fail to install with "path not found" errors.1023**Symptoms**: Added a marketplace via URL (such as `https://example.com/marketplace.json`), but plugins with relative path sources like `"./plugins/my-plugin"` fail to install with "path not found" errors.

plugins.md +69 −25

Details

24* You're customizing Claude Code for a single project24* You're customizing Claude Code for a single project

25* The configuration is personal and doesn't need to be shared25* The configuration is personal and doesn't need to be shared

26* You're experimenting with skills or hooks before packaging them26* You're experimenting with skills or hooks before packaging them

27* You want short skill names like `/hello` or `/review`27* You want short skill names like `/hello` or `/deploy`

28 28 

29**Use plugins when**:29**Use plugins when**:

30 30 


45### Prerequisites45### Prerequisites

46 46 

47* Claude Code [installed and authenticated](/en/quickstart#step-1-install-claude-code)47* Claude Code [installed and authenticated](/en/quickstart#step-1-install-claude-code)

48* Claude Code version 1.0.33 or later (run `claude --version` to check)

49 48 

50<Note>49<Note>

51 If you don't see the `/plugin` command, update Claude Code to the latest version. See [Troubleshooting](/en/troubleshooting) for upgrade instructions.50 If you don't see the `/plugin` command, update Claude Code to the latest version. See [Troubleshooting](/en/troubleshooting) for upgrade instructions.


85 ```84 ```

86 85 

87 | Field | Purpose |86 | Field | Purpose |

88 | :------------ | :----------------------------------------------------------------------------------------------------- |87 | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

89 | `name` | Unique identifier and skill namespace. Skills are prefixed with this (e.g., `/my-first-plugin:hello`). |88 | `name` | Unique identifier and skill namespace. Skills are prefixed with this (e.g., `/my-first-plugin:hello`). |

90 | `description` | Shown in the plugin manager when browsing or installing plugins. |89 | `description` | Shown in the plugin manager when browsing or installing plugins. |

91 | `version` | Track releases using [semantic versioning](/en/plugins-reference#version-management). |90 | `version` | Optional. If set, users only receive updates when you bump this field. If omitted and your plugin is distributed via git, the commit SHA is used and every commit counts as a new version. See [version management](/en/plugins-reference#version-management). |

92 | `author` | Optional. Helpful for attribution. |91 | `author` | Optional. Helpful for attribution. |

93 92 

94 For additional fields like `homepage`, `repository`, and `license`, see the [full manifest schema](/en/plugins-reference#plugin-manifest-schema).93 For additional fields like `homepage`, `repository`, and `license`, see the [full manifest schema](/en/plugins-reference#plugin-manifest-schema).


122 claude --plugin-dir ./my-first-plugin121 claude --plugin-dir ./my-first-plugin

123 ```122 ```

124 123 

125 Once Claude Code starts, try your new command:124 Once Claude Code starts, try your new skill:

126 125 

127 ```shell theme={null}126 ```shell theme={null}

128 /my-first-plugin:hello127 /my-first-plugin:hello

129 ```128 ```

130 129 

131 You'll see Claude respond with a greeting. Run `/help` to see your command listed under the plugin namespace.130 You'll see Claude respond with a greeting. Run `/help` to see your skill listed under the plugin namespace.

132 131 

133 <Note>132 <Note>

134 **Why namespacing?** Plugin skills are always namespaced (like `/greet:hello`) to prevent conflicts when multiple plugins have skills with the same name.133 **Why namespacing?** Plugin skills are always namespaced (like `/my-first-plugin:hello`) to prevent conflicts when multiple plugins have skills with the same name.

135 134 

136 To change the namespace prefix, update the `name` field in `plugin.json`.135 To change the namespace prefix, update the `name` field in `plugin.json`.

137 </Note>136 </Note>


140 <Step title="Add skill arguments">139 <Step title="Add skill arguments">

141 Make your skill dynamic by accepting user input. The `$ARGUMENTS` placeholder captures any text the user provides after the skill name.140 Make your skill dynamic by accepting user input. The `$ARGUMENTS` placeholder captures any text the user provides after the skill name.

142 141 

143 Update your `hello.md` file:142 Update your `SKILL.md` file:

144 143 

145 ```markdown my-first-plugin/commands/hello.md theme={null}144 ```markdown my-first-plugin/skills/hello/SKILL.md theme={null}

146 ---145 ---

147 description: Greet the user with a personalized message146 description: Greet the user with a personalized message

148 ---147 ---

149 148 

150 # Hello Command149 # Hello Skill

151 150 

152 Greet the user named "$ARGUMENTS" warmly and ask how you can help them today. Make the greeting personal and encouraging.151 Greet the user named "$ARGUMENTS" warmly and ask how you can help them today. Make the greeting personal and encouraging.

153 ```152 ```

154 153 

155 Restart Claude Code to pick up the changes, then try the command with your name:154 Run `/reload-plugins` to pick up the changes, then try the skill with your name:

156 155 

157 ```shell theme={null}156 ```shell theme={null}

158 /my-first-plugin:hello Alex157 /my-first-plugin:hello Alex


165You've successfully created and tested a plugin with these key components:164You've successfully created and tested a plugin with these key components:

166 165 

167* **Plugin manifest** (`.claude-plugin/plugin.json`): describes your plugin's metadata166* **Plugin manifest** (`.claude-plugin/plugin.json`): describes your plugin's metadata

168* **Commands directory** (`commands/`): contains your custom skills167* **Skills directory** (`skills/`): contains your custom skills

169* **Skill arguments** (`$ARGUMENTS`): captures user input for dynamic behavior168* **Skill arguments** (`$ARGUMENTS`): captures user input for dynamic behavior

170 169 

171<Tip>170<Tip>


174 173 

175## Plugin structure overview174## Plugin structure overview

176 175 

177You've created a plugin with a skill, but plugins can include much more: custom agents, hooks, MCP servers, and LSP servers.176You've created a plugin with a skill, but plugins can include much more: custom agents, hooks, MCP servers, LSP servers, and background monitors.

178 177 

179<Warning>178<Warning>

180 **Common mistake**: Don't put `commands/`, `agents/`, `skills/`, or `hooks/` inside the `.claude-plugin/` directory. Only `plugin.json` goes inside `.claude-plugin/`. All other directories must be at the plugin root level.179 **Common mistake**: Don't put `commands/`, `agents/`, `skills/`, or `hooks/` inside the `.claude-plugin/` directory. Only `plugin.json` goes inside `.claude-plugin/`. All other directories must be at the plugin root level.

181</Warning>180</Warning>

182 181 

183| Directory | Location | Purpose |182| Directory | Location | Purpose |

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

185| `.claude-plugin/` | Plugin root | Contains only `plugin.json` manifest (required) |184| `.claude-plugin/` | Plugin root | Contains `plugin.json` manifest (optional if components use default locations) |

186| `commands/` | Plugin root | Skills as Markdown files |185| `skills/` | Plugin root | Skills as `<name>/SKILL.md` directories |

186| `commands/` | Plugin root | Skills as flat Markdown files. Use `skills/` for new plugins |

187| `agents/` | Plugin root | Custom agent definitions |187| `agents/` | Plugin root | Custom agent definitions |

188| `skills/` | Plugin root | Agent Skills with `SKILL.md` files |

189| `hooks/` | Plugin root | Event handlers in `hooks.json` |188| `hooks/` | Plugin root | Event handlers in `hooks.json` |

190| `.mcp.json` | Plugin root | MCP server configurations |189| `.mcp.json` | Plugin root | MCP server configurations |

191| `.lsp.json` | Plugin root | LSP server configurations for code intelligence |190| `.lsp.json` | Plugin root | LSP server configurations for code intelligence |

191| `monitors/` | Plugin root | Background monitor configurations in `monitors.json` |

192| `bin/` | Plugin root | Executables added to the Bash tool's `PATH` while the plugin is enabled |

193| `settings.json` | Plugin root | Default [settings](/en/settings) applied when the plugin is enabled |

192 194 

193<Note>195<Note>

194 **Next steps**: Ready to add more features? Jump to [Develop more complex plugins](#develop-more-complex-plugins) to add agents, hooks, MCP servers, and LSP servers. For complete technical specifications of all plugin components, see [Plugins reference](/en/plugins-reference).196 **Next steps**: Ready to add more features? Jump to [Develop more complex plugins](#develop-more-complex-plugins) to add agents, hooks, MCP servers, and LSP servers. For complete technical specifications of all plugin components, see [Plugins reference](/en/plugins-reference).


204 206 

205Add a `skills/` directory at your plugin root with Skill folders containing `SKILL.md` files:207Add a `skills/` directory at your plugin root with Skill folders containing `SKILL.md` files:

206 208 

207```209```text theme={null}

208my-plugin/210my-plugin/

209├── .claude-plugin/211├── .claude-plugin/

210│ └── plugin.json212│ └── plugin.json


213 └── SKILL.md215 └── SKILL.md

214```216```

215 217 

216Each `SKILL.md` needs frontmatter with `name` and `description` fields, followed by instructions:218Each `SKILL.md` contains YAML frontmatter and instructions. Include a `description` so Claude knows when to use the skill:

217 219 

218```yaml theme={null}220```yaml theme={null}

219---221---

220name: code-review

221description: Reviews code for best practices and potential issues. Use when reviewing code, checking PRs, or analyzing code quality.222description: Reviews code for best practices and potential issues. Use when reviewing code, checking PRs, or analyzing code quality.

222---223---

223 224 


2284. Test coverage2294. Test coverage

229```230```

230 231 

231After installing the plugin, restart Claude Code to load the Skills. For complete Skill authoring guidance including progressive disclosure and tool restrictions, see [Agent Skills](/en/skills).232After installing the plugin, run `/reload-plugins` to load the Skills. For complete Skill authoring guidance including progressive disclosure and tool restrictions, see [Agent Skills](/en/skills).

232 233 

233### Add LSP servers to your plugin234### Add LSP servers to your plugin

234 235 


254 255 

255For complete LSP configuration options, see [LSP servers](/en/plugins-reference#lsp-servers).256For complete LSP configuration options, see [LSP servers](/en/plugins-reference#lsp-servers).

256 257 

258### Add background monitors to your plugin

259 

260Background monitors let your plugin watch logs, files, or external status in the background and notify Claude as events arrive. Claude Code starts each monitor automatically when the plugin is active, so you don't need to instruct Claude to start the watch.

261 

262Add a `monitors/monitors.json` file at the plugin root with an array of monitor entries:

263 

264```json monitors/monitors.json theme={null}

265[

266 {

267 "name": "error-log",

268 "command": "tail -F ./logs/error.log",

269 "description": "Application error log"

270 }

271]

272```

273 

274Each stdout line from `command` is delivered to Claude as a notification during the session. For the full schema, including the `when` trigger and variable substitution, see [Monitors](/en/plugins-reference#monitors).

275 

276### Ship default settings with your plugin

277 

278Plugins can include a `settings.json` file at the plugin root to apply default configuration when the plugin is enabled. Currently, only the `agent` and `subagentStatusLine` keys are supported.

279 

280Setting `agent` activates one of the plugin's [custom agents](/en/sub-agents) as the main thread, applying its system prompt, tool restrictions, and model. This lets a plugin change how Claude Code behaves by default when enabled.

281 

282```json settings.json theme={null}

283{

284 "agent": "security-reviewer"

285}

286```

287 

288This example activates the `security-reviewer` agent defined in the plugin's `agents/` directory. Settings from `settings.json` take priority over `settings` declared in `plugin.json`. Unknown keys are silently ignored.

289 

257### Organize complex plugins290### Organize complex plugins

258 291 

259For plugins with many components, organize your directory structure by functionality. For complete directory layouts and organization patterns, see [Plugin directory structure](/en/plugins-reference#plugin-directory-structure).292For plugins with many components, organize your directory structure by functionality. For complete directory layouts and organization patterns, see [Plugin directory structure](/en/plugins-reference#plugin-directory-structure).


266claude --plugin-dir ./my-plugin299claude --plugin-dir ./my-plugin

267```300```

268 301 

269As you make changes to your plugin, restart Claude Code to pick up the updates. Test your plugin components:302When 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.

270 303 

271* Try your commands with `/command-name`304As 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:

305 

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

272* Check that agents appear in `/agents`307* Check that agents appear in `/agents`

273* Verify hooks work as expected308* Verify hooks work as expected

274 309 


285If your plugin isn't working as expected:320If your plugin isn't working as expected:

286 321 

2871. **Check the structure**: Ensure your directories are at the plugin root, not inside `.claude-plugin/`3221. **Check the structure**: Ensure your directories are at the plugin root, not inside `.claude-plugin/`

2882. **Test components individually**: Check each command, agent, and hook separately3232. **Test components individually**: Check each skill, agent, and hook separately

2893. **Use validation and debugging tools**: See [Debugging and development tools](/en/plugins-reference#debugging-and-development-tools) for CLI commands and troubleshooting techniques3243. **Use validation and debugging tools**: See [Debugging and development tools](/en/plugins-reference#debugging-and-development-tools) for CLI commands and troubleshooting techniques

290 325 

291### Share your plugins326### Share your plugins


293When your plugin is ready to share:328When your plugin is ready to share:

294 329 

2951. **Add documentation**: Include a `README.md` with installation and usage instructions3301. **Add documentation**: Include a `README.md` with installation and usage instructions

2962. **Version your plugin**: Use [semantic versioning](/en/plugins-reference#version-management) in your `plugin.json`3312. **Choose a versioning strategy**: Decide whether to set an explicit `version` or rely on the git commit SHA. See [version management](/en/plugins-reference#version-management)

2973. **Create or use a marketplace**: Distribute through [plugin marketplaces](/en/plugin-marketplaces) for installation3323. **Create or use a marketplace**: Distribute through [plugin marketplaces](/en/plugin-marketplaces) for installation

2984. **Test with others**: Have team members test the plugin before wider distribution3334. **Test with others**: Have team members test the plugin before wider distribution

299 334 

300Once your plugin is in a marketplace, others can install it using the instructions in [Discover and install plugins](/en/discover-plugins).335Once your plugin is in a marketplace, others can install it using the instructions in [Discover and install plugins](/en/discover-plugins).

301 336 

337### Submit your plugin to the official marketplace

338 

339To submit a plugin to the official Anthropic marketplace, use one of the in-app submission forms:

340 

341* **Claude.ai**: [claude.ai/settings/plugins/submit](https://claude.ai/settings/plugins/submit)

342* **Console**: [platform.claude.com/plugins/submit](https://platform.claude.com/plugins/submit)

343 

344Once your plugin is listed, you can have your own CLI prompt Claude Code users to install it. See [Recommend your plugin from your CLI](/en/plugin-hints).

345 

302<Note>346<Note>

303 For complete technical specifications, debugging techniques, and distribution strategies, see [Plugins reference](/en/plugins-reference).347 For complete technical specifications, debugging techniques, and distribution strategies, see [Plugins reference](/en/plugins-reference).

304</Note>348</Note>

plugins-reference.md +385 −134

Details

12 12 

13This reference provides complete technical specifications for the Claude Code plugin system, including component schemas, CLI commands, and development tools.13This reference provides complete technical specifications for the Claude Code plugin system, including component schemas, CLI commands, and development tools.

14 14 

15## Plugin components reference15A **plugin** is a self-contained directory of components that extends Claude Code with custom functionality. Plugin components include skills, agents, hooks, MCP servers, LSP servers, and monitors.

16 16 

17This section documents the types of components that plugins can provide.17## Plugin components reference

18 18 

19### Skills19### Skills

20 20 


26 26 

27**Skill structure**:27**Skill structure**:

28 28 

29```29```text theme={null}

30skills/30skills/

31├── pdf-processor/31├── pdf-processor/

32│ ├── SKILL.md32│ ├── SKILL.md


56 56 

57```markdown theme={null}57```markdown theme={null}

58---58---

59description: What this agent specializes in59name: agent-name

60capabilities: ["task1", "task2", "task3"]60description: What this agent specializes in and when Claude should invoke it

61model: sonnet

62effort: medium

63maxTurns: 20

64disallowedTools: Write, Edit

61---65---

62 66 

63# Agent Name67Detailed system prompt for the agent describing its role, expertise, and behavior.

64 

65Detailed description of the agent's role, expertise, and when Claude should invoke it.

66 

67## Capabilities

68- Specific task the agent excels at

69- Another specialized capability

70- When to use this agent vs others

71 

72## Context and examples

73Provide examples of when this agent should be used and what kinds of problems it solves.

74```68```

75 69 

70Plugin agents support `name`, `description`, `model`, `effort`, `maxTurns`, `tools`, `disallowedTools`, `skills`, `memory`, `background`, and `isolation` frontmatter fields. The only valid `isolation` value is `"worktree"`. For security reasons, `hooks`, `mcpServers`, and `permissionMode` are not supported for plugin-shipped agents.

71 

76**Integration points**:72**Integration points**:

77 73 

78* Agents appear in the `/agents` interface74* Agents appear in the `/agents` interface


80* Agents can be invoked manually by users76* Agents can be invoked manually by users

81* Plugin agents work alongside built-in Claude agents77* Plugin agents work alongside built-in Claude agents

82 78 

79For complete details, see [Subagents](/en/sub-agents).

80 

83### Hooks81### Hooks

84 82 

85Plugins can provide event handlers that respond to Claude Code events automatically.83Plugins can provide event handlers that respond to Claude Code events automatically.


108}106}

109```107```

110 108 

111**Available events**:109Plugin hooks respond to the same lifecycle events as [user-defined hooks](/en/hooks):

112 110 

113* `PreToolUse`: Before Claude uses any tool111| Event | When it fires |

114* `PostToolUse`: After Claude successfully uses any tool112| :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- |

115* `PostToolUseFailure`: After Claude tool execution fails113| `SessionStart` | When a session begins or resumes |

116* `PermissionRequest`: When a permission dialog is shown114| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |

117* `UserPromptSubmit`: When user submits a prompt115| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |

118* `Notification`: When Claude Code sends notifications116| `PreToolUse` | Before a tool call executes. Can block it |

119* `Stop`: When Claude attempts to stop117| `PermissionRequest` | When a permission dialog appears |

120* `SubagentStart`: When a subagent is started118| `PermissionDenied` | When a tool call is denied by the auto mode classifier. Return `{retry: true}` to tell the model it may retry the denied tool call |

121* `SubagentStop`: When a subagent attempts to stop119| `PostToolUse` | After a tool call succeeds |

122* `SessionStart`: At the beginning of sessions120| `PostToolUseFailure` | After a tool call fails |

123* `SessionEnd`: At the end of sessions121| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |

124* `PreCompact`: Before conversation history is compacted122| `Notification` | When Claude Code sends a notification |

123| `SubagentStart` | When a subagent is spawned |

124| `SubagentStop` | When a subagent finishes |

125| `TaskCreated` | When a task is being created via `TaskCreate` |

126| `TaskCompleted` | When a task is being marked as completed |

127| `Stop` | When Claude finishes responding |

128| `StopFailure` | When the turn ends due to an API error. Output and exit code are ignored |

129| `TeammateIdle` | When an [agent team](/en/agent-teams) teammate is about to go idle |

130| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |

131| `ConfigChange` | When a configuration file changes during a session |

132| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |

133| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |

134| `WorktreeCreate` | When a worktree is being created via `--worktree` or `isolation: "worktree"`. Replaces default git behavior |

135| `WorktreeRemove` | When a worktree is being removed, either at session exit or when a subagent finishes |

136| `PreCompact` | Before context compaction |

137| `PostCompact` | After context compaction completes |

138| `Elicitation` | When an MCP server requests user input during a tool call |

139| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |

140| `SessionEnd` | When a session terminates |

125 141 

126**Hook types**:142**Hook types**:

127 143 

128* `command`: Execute shell commands or scripts144* `command`: execute shell commands or scripts

129* `prompt`: Evaluate a prompt with an LLM (uses `$ARGUMENTS` placeholder for context)145* `http`: send the event JSON as a POST request to a URL

130* `agent`: Run an agentic verifier with tools for complex verification tasks146* `mcp_tool`: call a tool on a configured [MCP server](/en/mcp)

147* `prompt`: evaluate a prompt with an LLM (uses `$ARGUMENTS` placeholder for context)

148* `agent`: run an agentic verifier with tools for complex verification tasks

131 149 

132### MCP servers150### MCP servers

133 151 


168### LSP servers186### LSP servers

169 187 

170<Tip>188<Tip>

171 Looking to use LSP plugins? Install them from the official marketplacesearch for "lsp" in the `/plugin` Discover tab. This section documents how to create LSP plugins for languages not covered by the official marketplace.189 Looking to use LSP plugins? Install them from the official marketplace: search for "lsp" in the `/plugin` Discover tab. This section documents how to create LSP plugins for languages not covered by the official marketplace.

172</Tip>190</Tip>

173 191 

174Plugins can provide [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) (LSP) servers to give Claude real-time code intelligence while working on your codebase.192Plugins can provide [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) (LSP) servers to give Claude real-time code intelligence while working on your codebase.


250 268 

251Install the language server first, then install the plugin from the marketplace.269Install the language server first, then install the plugin from the marketplace.

252 270 

271### Monitors

272 

273Plugins can declare background monitors that Claude Code starts automatically when the plugin is active. Each monitor runs a shell command for the lifetime of the session and delivers every stdout line to Claude as a notification, so Claude can react to log entries, status changes, or polled events without being asked to start the watch itself.

274 

275Plugin monitors use the same mechanism as the [Monitor tool](/en/tools-reference#monitor-tool) and share its availability constraints. They run only in interactive CLI sessions, run unsandboxed at the same trust level as [hooks](#hooks), and are skipped on hosts where the Monitor tool is unavailable.

276 

277<Note>

278 Plugin monitors require Claude Code v2.1.105 or later.

279</Note>

280 

281**Location**: `monitors/monitors.json` in the plugin root, or inline in `plugin.json`

282 

283**Format**: JSON array of monitor entries

284 

285The following `monitors/monitors.json` watches a deployment status endpoint and a local error log:

286 

287```json theme={null}

288[

289 {

290 "name": "deploy-status",

291 "command": "${CLAUDE_PLUGIN_ROOT}/scripts/poll-deploy.sh ${user_config.api_endpoint}",

292 "description": "Deployment status changes"

293 },

294 {

295 "name": "error-log",

296 "command": "tail -F ./logs/error.log",

297 "description": "Application error log",

298 "when": "on-skill-invoke:debug"

299 }

300]

301```

302 

303To declare monitors inline, set the `monitors` key in `plugin.json` to the same array. To load from a non-default path, set `monitors` to a relative path string such as `"./config/monitors.json"`.

304 

305**Required fields:**

306 

307| Field | Description |

308| :------------ | :-------------------------------------------------------------------------------------------------------------------- |

309| `name` | Identifier unique within the plugin. Prevents duplicate processes when the plugin reloads or a skill is invoked again |

310| `command` | Shell command run as a persistent background process in the session working directory |

311| `description` | Short summary of what is being watched. Shown in the task panel and in notification summaries |

312 

313**Optional fields:**

314 

315| Field | Description |

316| :----- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

317| `when` | Controls when the monitor starts. `"always"` starts it at session start and on plugin reload, and is the default. `"on-skill-invoke:<skill-name>"` starts it the first time the named skill in this plugin is dispatched |

318 

319The `command` value supports the same [variable substitutions](#environment-variables) as MCP and LSP server configs: `${CLAUDE_PLUGIN_ROOT}`, `${CLAUDE_PLUGIN_DATA}`, `${user_config.*}`, and any `${ENV_VAR}` from the environment. Prefix the command with `cd "${CLAUDE_PLUGIN_ROOT}" && ` if the script needs to run from the plugin's own directory.

320 

321Disabling a plugin mid-session does not stop monitors that are already running. They stop when the session ends.

322 

323### Themes

324 

325Plugins can ship color themes that appear in `/theme` alongside the built-in presets and the user's local themes. A theme is a JSON file in `themes/` with a `base` preset and a sparse `overrides` map of color tokens.

326 

327```json theme={null}

328{

329 "name": "Dracula",

330 "base": "dark",

331 "overrides": {

332 "claude": "#bd93f9",

333 "error": "#ff5555",

334 "success": "#50fa7b"

335 }

336}

337```

338 

339Selecting a plugin theme persists `custom:<plugin-name>:<slug>` in the user's config. Plugin themes are read-only; pressing `Ctrl+E` on one in `/theme` copies it into `~/.claude/themes/` so the user can edit the copy.

340 

253***341***

254 342 

255## Plugin installation scopes343## Plugin installation scopes


257When you install a plugin, you choose a **scope** that determines where the plugin is available and who else can use it:345When you install a plugin, you choose a **scope** that determines where the plugin is available and who else can use it:

258 346 

259| Scope | Settings file | Use case |347| Scope | Settings file | Use case |

260| :-------- | :---------------------------- | :------------------------------------------------------- |348| :-------- | :---------------------------------------------- | :------------------------------------------------------- |

261| `user` | `~/.claude/settings.json` | Personal plugins available across all projects (default) |349| `user` | `~/.claude/settings.json` | Personal plugins available across all projects (default) |

262| `project` | `.claude/settings.json` | Team plugins shared via version control |350| `project` | `.claude/settings.json` | Team plugins shared via version control |

263| `local` | `.claude/settings.local.json` | Project-specific plugins, gitignored |351| `local` | `.claude/settings.local.json` | Project-specific plugins, gitignored |

264| `managed` | `managed-settings.json` | Managed plugins (read-only, update only) |352| `managed` | [Managed settings](/en/settings#settings-files) | Managed plugins (read-only, update only) |

265 353 

266Plugins use the same scope system as other Claude Code configurations. For installation instructions and scope flags, see [Install plugins](/en/discover-plugins#install-plugins). For a complete explanation of scopes, see [Configuration scopes](/en/settings#configuration-scopes).354Plugins use the same scope system as other Claude Code configurations. For installation instructions and scope flags, see [Install plugins](/en/discover-plugins#install-plugins). For a complete explanation of scopes, see [Configuration scopes](/en/settings#configuration-scopes).

267 355 


269 357 

270## Plugin manifest schema358## Plugin manifest schema

271 359 

272The `plugin.json` file defines your plugin's metadata and configuration. This section documents all supported fields and options.360The `.claude-plugin/plugin.json` file defines your plugin's metadata and configuration. This section documents all supported fields and options.

361 

362The manifest is optional. If omitted, Claude Code auto-discovers components in [default locations](#file-locations-reference) and derives the plugin name from the directory name. Use a manifest when you need to provide metadata or custom component paths.

273 363 

274### Complete schema364### Complete schema

275 365 


287 "repository": "https://github.com/author/plugin",377 "repository": "https://github.com/author/plugin",

288 "license": "MIT",378 "license": "MIT",

289 "keywords": ["keyword1", "keyword2"],379 "keywords": ["keyword1", "keyword2"],

380 "skills": "./custom/skills/",

290 "commands": ["./custom/commands/special.md"],381 "commands": ["./custom/commands/special.md"],

291 "agents": "./custom/agents/",382 "agents": "./custom/agents/",

292 "skills": "./custom/skills/",

293 "hooks": "./config/hooks.json",383 "hooks": "./config/hooks.json",

294 "mcpServers": "./mcp-config.json",384 "mcpServers": "./mcp-config.json",

295 "outputStyles": "./styles/",385 "outputStyles": "./styles/",

296 "lspServers": "./.lsp.json"386 "themes": "./themes/",

387 "lspServers": "./.lsp.json",

388 "monitors": "./monitors.json",

389 "dependencies": [

390 "helper-lib",

391 { "name": "secrets-vault", "version": "~2.1.0" }

392 ]

297}393}

298```394```

299 395 

300### Required fields396### Required fields

301 397 

398If you include a manifest, `name` is the only required field.

399 

302| Field | Type | Description | Example |400| Field | Type | Description | Example |

303| :----- | :----- | :---------------------------------------- | :------------------- |401| :----- | :----- | :---------------------------------------- | :------------------- |

304| `name` | string | Unique identifier (kebab-case, no spaces) | `"deployment-tools"` |402| `name` | string | Unique identifier (kebab-case, no spaces) | `"deployment-tools"` |

305 403 

404This name is used for namespacing components. For example, in the UI, the

405agent `agent-creator` for the plugin with name `plugin-dev` will appear as

406`plugin-dev:agent-creator`.

407 

306### Metadata fields408### Metadata fields

307 409 

308| Field | Type | Description | Example |410| Field | Type | Description | Example |

309| :------------ | :----- | :---------------------------------- | :------------------------------------------------- |411| :------------ | :----- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------- |

310| `version` | string | Semantic version | `"2.1.0"` |412| `version` | string | Optional. Semantic version. Setting this pins the plugin to that version string, so users only receive updates when you bump it. If omitted, Claude Code falls back to the git commit SHA, so every commit is treated as a new version. If also set in the marketplace entry, `plugin.json` wins. See [Version management](#version-management). | `"2.1.0"` |

311| `description` | string | Brief explanation of plugin purpose | `"Deployment automation tools"` |413| `description` | string | Brief explanation of plugin purpose | `"Deployment automation tools"` |

312| `author` | object | Author information | `{"name": "Dev Team", "email": "dev@company.com"}` |414| `author` | object | Author information | `{"name": "Dev Team", "email": "dev@company.com"}` |

313| `homepage` | string | Documentation URL | `"https://docs.example.com"` |415| `homepage` | string | Documentation URL | `"https://docs.example.com"` |


318### Component path fields420### Component path fields

319 421 

320| Field | Type | Description | Example |422| Field | Type | Description | Example |

321| :------------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- |423| :------------- | :-------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------- |

322| `commands` | string\|array | Additional command files/directories | `"./custom/cmd.md"` or `["./cmd1.md"]` |424| `skills` | string\|array | Custom skill directories containing `<name>/SKILL.md` (replaces default `skills/`) | `"./custom/skills/"` |

323| `agents` | string\|array | Additional agent files | `"./custom/agents/"` |425| `commands` | string\|array | Custom flat `.md` skill files or directories (replaces default `commands/`) | `"./custom/cmd.md"` or `["./cmd1.md"]` |

324| `skills` | string\|array | Additional skill directories | `"./custom/skills/"` |426| `agents` | string\|array | Custom agent files (replaces default `agents/`) | `"./custom/agents/reviewer.md"` |

325| `hooks` | string\|object | Hook config path or inline config | `"./hooks.json"` |427| `hooks` | string\|array\|object | Hook config paths or inline config | `"./my-extra-hooks.json"` |

326| `mcpServers` | string\|object | MCP config path or inline config | `"./mcp-config.json"` |428| `mcpServers` | string\|array\|object | MCP config paths or inline config | `"./my-extra-mcp-config.json"` |

327| `outputStyles` | string\|array | Additional output style files/directories | `"./styles/"` |429| `outputStyles` | string\|array | Custom output style files/directories (replaces default `output-styles/`) | `"./styles/"` |

328| `lspServers` | string\|object | [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) config for code intelligence (go to definition, find references, etc.) | `"./.lsp.json"` |430| `themes` | string\|array | Color theme files/directories (replaces default `themes/`). See [Themes](#themes) | `"./themes/"` |

431| `lspServers` | string\|array\|object | [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) configs for code intelligence (go to definition, find references, etc.) | `"./.lsp.json"` |

432| `monitors` | string\|array | Background [Monitor](/en/tools-reference#monitor-tool) configurations that start automatically when the plugin is active. See [Monitors](#monitors) | `"./monitors.json"` |

433| `userConfig` | object | User-configurable values prompted at enable time. See [User configuration](#user-configuration) | See below |

434| `channels` | array | Channel declarations for message injection (Telegram, Slack, Discord style). See [Channels](#channels) | See below |

435| `dependencies` | array | Other plugins this plugin requires, optionally with semver version constraints. See [Constrain plugin dependency versions](/en/plugin-dependencies) | `[{ "name": "secrets-vault", "version": "~2.1.0" }]` |

436 

437### User configuration

438 

439The `userConfig` field declares values that Claude Code prompts the user for when the plugin is enabled. Use this instead of requiring users to hand-edit `settings.json`.

440 

441```json theme={null}

442{

443 "userConfig": {

444 "api_endpoint": {

445 "type": "string",

446 "title": "API endpoint",

447 "description": "Your team's API endpoint"

448 },

449 "api_token": {

450 "type": "string",

451 "title": "API token",

452 "description": "API authentication token",

453 "sensitive": true

454 }

455 }

456}

457```

458 

459Keys must be valid identifiers. Each option supports these fields:

460 

461| Field | Required | Description |

462| :------------ | :------- | :--------------------------------------------------------------------------------------- |

463| `type` | Yes | One of `string`, `number`, `boolean`, `directory`, or `file` |

464| `title` | Yes | Label shown in the configuration dialog |

465| `description` | Yes | Help text shown beneath the field |

466| `sensitive` | No | If `true`, masks input and stores the value in secure storage instead of `settings.json` |

467| `required` | No | If `true`, validation fails when the field is empty |

468| `default` | No | Value used when the user provides nothing |

469| `multiple` | No | For `string` type, allow an array of strings |

470| `min` / `max` | No | Bounds for `number` type |

471 

472Each value is available for substitution as `${user_config.KEY}` in MCP and LSP server configs, hook commands, and monitor commands. Non-sensitive values can also be substituted in skill and agent content. All values are exported to plugin subprocesses as `CLAUDE_PLUGIN_OPTION_<KEY>` environment variables.

473 

474Non-sensitive values are stored in `settings.json` under `pluginConfigs[<plugin-id>].options`. Sensitive values go to the system keychain (or `~/.claude/.credentials.json` where the keychain is unavailable). Keychain storage is shared with OAuth tokens and has an approximately 2 KB total limit, so keep sensitive values small.

475 

476### Channels

477 

478The `channels` field lets a plugin declare one or more message channels that inject content into the conversation. Each channel binds to an MCP server that the plugin provides.

479 

480```json theme={null}

481{

482 "channels": [

483 {

484 "server": "telegram",

485 "userConfig": {

486 "bot_token": {

487 "type": "string",

488 "title": "Bot token",

489 "description": "Telegram bot token",

490 "sensitive": true

491 },

492 "owner_id": {

493 "type": "string",

494 "title": "Owner ID",

495 "description": "Your Telegram user ID"

496 }

497 }

498 }

499 ]

500}

501```

502 

503The `server` field is required and must match a key in the plugin's `mcpServers`. The optional per-channel `userConfig` uses the same schema as the top-level field, letting the plugin prompt for bot tokens or owner IDs when the plugin is enabled.

329 504 

330### Path behavior rules505### Path behavior rules

331 506 

332**Important**: Custom paths supplement default directories - they don't replace them.507For `skills`, `commands`, `agents`, `outputStyles`, `themes`, and `monitors`, a custom path replaces the default. If the manifest specifies `skills`, the default `skills/` directory is not scanned; if it specifies `monitors`, the default `monitors/monitors.json` is not loaded. [Hooks](#hooks), [MCP servers](#mcp-servers), and [LSP servers](#lsp-servers) have different semantics for handling multiple sources.

333 508 

334* If `commands/` exists, it's loaded in addition to custom command paths509* All paths must be relative to the plugin root and start with `./`

335* All paths must be relative to plugin root and start with `./`510* Components from custom paths use the same naming and namespacing rules

336* Commands from custom paths use the same naming and namespacing rules511* Multiple paths can be specified as arrays

337* Multiple paths can be specified as arrays for flexibility512* To keep the default directory and add more paths for skills, commands, agents, or output styles, include the default in your array: `"skills": ["./skills/", "./extras/"]`

513* When a skill path points to a directory that contains a `SKILL.md` directly, for example `"skills": ["./"]` pointing to the plugin root, the frontmatter `name` field in `SKILL.md` determines the skill's invocation name. This gives a stable name regardless of the install directory. If `name` is not set in the frontmatter, the directory basename is used as a fallback.

338 514 

339**Path examples**:515**Path examples**:

340 516 


353 529 

354### Environment variables530### Environment variables

355 531 

356**`${CLAUDE_PLUGIN_ROOT}`**: Contains the absolute path to your plugin directory. Use this in hooks, MCP servers, and scripts to ensure correct paths regardless of installation location.532Claude Code provides two variables for referencing plugin paths. Both are substituted inline anywhere they appear in skill content, agent content, hook commands, monitor commands, and MCP or LSP server configs. Both are also exported as environment variables to hook processes and MCP or LSP server subprocesses.

533 

534**`${CLAUDE_PLUGIN_ROOT}`**: the absolute path to your plugin's installation directory. Use this to reference scripts, binaries, and config files bundled with the plugin. This path changes when the plugin updates, so files you write here do not survive an update.

535 

536**`${CLAUDE_PLUGIN_DATA}`**: a persistent directory for plugin state that survives updates. Use this for installed dependencies such as `node_modules` or Python virtual environments, generated code, caches, and any other files that should persist across plugin versions. The directory is created automatically the first time this variable is referenced.

357 537 

358```json theme={null}538```json theme={null}

359{539{


372}552}

373```553```

374 554 

375***555#### Persistent data directory

376 556 

377## Plugin caching and file resolution557The `${CLAUDE_PLUGIN_DATA}` directory resolves to `~/.claude/plugins/data/{id}/`, where `{id}` is the plugin identifier with characters outside `a-z`, `A-Z`, `0-9`, `_`, and `-` replaced by `-`. For a plugin installed as `formatter@my-marketplace`, the directory is `~/.claude/plugins/data/formatter-my-marketplace/`.

558 

559A common use is installing language dependencies once and reusing them across sessions and plugin updates. Because the data directory outlives any single plugin version, a check for directory existence alone cannot detect when an update changes the plugin's dependency manifest. The recommended pattern compares the bundled manifest against a copy in the data directory and reinstalls when they differ.

560 

561This `SessionStart` hook installs `node_modules` on the first run and again whenever a plugin update includes a changed `package.json`:

562 

563```json theme={null}

564{

565 "hooks": {

566 "SessionStart": [

567 {

568 "hooks": [

569 {

570 "type": "command",

571 "command": "diff -q \"${CLAUDE_PLUGIN_ROOT}/package.json\" \"${CLAUDE_PLUGIN_DATA}/package.json\" >/dev/null 2>&1 || (cd \"${CLAUDE_PLUGIN_DATA}\" && cp \"${CLAUDE_PLUGIN_ROOT}/package.json\" . && npm install) || rm -f \"${CLAUDE_PLUGIN_DATA}/package.json\""

572 }

573 ]

574 }

575 ]

576 }

577}

578```

579 

580The `diff` exits nonzero when the stored copy is missing or differs from the bundled one, covering both first run and dependency-changing updates. If `npm install` fails, the trailing `rm` removes the copied manifest so the next session retries.

378 581 

379For security and verification purposes, Claude Code copies plugins to a cache directory rather than using them in-place. Understanding this behavior is important when developing plugins that reference external files.582Scripts bundled in `${CLAUDE_PLUGIN_ROOT}` can then run against the persisted `node_modules`:

380 583 

381### How plugin caching works584```json theme={null}

585{

586 "mcpServers": {

587 "routines": {

588 "command": "node",

589 "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"],

590 "env": {

591 "NODE_PATH": "${CLAUDE_PLUGIN_DATA}/node_modules"

592 }

593 }

594 }

595}

596```

382 597 

383When you install a plugin, Claude Code copies the plugin files to a cache directory:598The data directory is deleted automatically when you uninstall the plugin from the last scope where it is installed. The `/plugin` interface shows the directory size and prompts before deleting. The CLI deletes by default; pass [`--keep-data`](#plugin-uninstall) to preserve it.

384 599 

385* **For marketplace plugins with relative paths**: The path specified in the `source` field is copied recursively. For example, if your marketplace entry specifies `"source": "./plugins/my-plugin"`, the entire `./plugins` directory is copied.600***

386* **For plugins with `.claude-plugin/plugin.json`**: The implicit root directory (the directory containing `.claude-plugin/plugin.json`) is copied recursively.

387 601 

388### Path traversal limitations602## Plugin caching and file resolution

389 603 

390Plugins cannot reference files outside their copied directory structure. Paths that traverse outside the plugin root (such as `../shared-utils`) will not work after installation because those external files are not copied to the cache.604Plugins are specified in one of two ways:

391 605 

392### Working with external dependencies606* Through `claude --plugin-dir`, for the duration of a session.

607* Through a marketplace, installed for future sessions.

393 608 

394If your plugin needs to access files outside its directory, you have two options:609For security and verification purposes, Claude Code copies *marketplace* plugins to the user's local **plugin cache** (`~/.claude/plugins/cache`) rather than using them in-place. Understanding this behavior is important when developing plugins that reference external files.

395 610 

396**Option 1: Use symlinks**611Each installed version is a separate directory in the cache. When you update or uninstall a plugin, the previous version directory is marked as orphaned and removed automatically 7 days later. The grace period lets concurrent Claude Code sessions that already loaded the old version keep running without errors.

397 612 

398Create symbolic links to external files within your plugin directory. Symlinks are honored during the copy process:613Claude's Glob and Grep tools skip orphaned version directories during searches, so file results don't include outdated plugin code.

399 614 

400```bash theme={null}615### Path traversal limitations

401# Inside your plugin directory

402ln -s /path/to/shared-utils ./shared-utils

403```

404 616 

405The symlinked content will be copied into the plugin cache.617Installed plugins cannot reference files outside their directory. Paths that traverse outside the plugin root (such as `../shared-utils`) will not work after installation because those external files are not copied to the cache.

406 618 

407**Option 2: Restructure your marketplace**619### Working with external dependencies

408 620 

409Set the plugin path to a parent directory that contains all required files, then provide the rest of the plugin manifest directly in the marketplace entry:621If your plugin needs to access files outside its directory, you can create symbolic links to external files within your plugin directory. Symlinks are preserved in the cache rather than dereferenced, and they resolve to their target at runtime. The following command creates a link from inside your plugin directory to a shared utilities location:

410 622 

411```json theme={null}623```bash theme={null}

412{624ln -s /path/to/shared-utils ./shared-utils

413 "name": "my-plugin",

414 "source": "./",

415 "description": "Plugin that needs root-level access",

416 "commands": ["./plugins/my-plugin/commands/"],

417 "agents": ["./plugins/my-plugin/agents/"],

418 "strict": false

419}

420```625```

421 626 

422This approach copies the entire marketplace root, giving your plugin access to sibling directories.627This provides flexibility while maintaining the security benefits of the caching system.

423 

424<Note>

425 Symlinks that point to locations outside the plugin's logical root are followed during copying. This provides flexibility while maintaining the security benefits of the caching system.

426</Note>

427 628 

428***629***

429 630 


433 634 

434A complete plugin follows this structure:635A complete plugin follows this structure:

435 636 

436```637```text theme={null}

437enterprise-plugin/638enterprise-plugin/

438├── .claude-plugin/ # Metadata directory639├── .claude-plugin/ # Metadata directory (optional)

439│ └── plugin.json # Required: plugin manifest640│ └── plugin.json # plugin manifest

440├── commands/ # Default command location641├── skills/ # Skills

441│ ├── status.md

442│ └── logs.md

443├── agents/ # Default agent location

444│ ├── security-reviewer.md

445│ ├── performance-tester.md

446│ └── compliance-checker.md

447├── skills/ # Agent Skills

448│ ├── code-reviewer/642│ ├── code-reviewer/

449│ │ └── SKILL.md643│ │ └── SKILL.md

450│ └── pdf-processor/644│ └── pdf-processor/

451│ ├── SKILL.md645│ ├── SKILL.md

452│ └── scripts/646│ └── scripts/

647├── commands/ # Skills as flat .md files

648│ ├── status.md

649│ └── logs.md

650├── agents/ # Subagent definitions

651│ ├── security-reviewer.md

652│ ├── performance-tester.md

653│ └── compliance-checker.md

654├── output-styles/ # Output style definitions

655│ └── terse.md

656├── themes/ # Color theme definitions

657│ └── dracula.json

658├── monitors/ # Background monitor configurations

659│ └── monitors.json

453├── hooks/ # Hook configurations660├── hooks/ # Hook configurations

454│ ├── hooks.json # Main hook config661│ ├── hooks.json # Main hook config

455│ └── security-hooks.json # Additional hooks662│ └── security-hooks.json # Additional hooks

663├── bin/ # Plugin executables added to PATH

664│ └── my-tool # Invokable as bare command in Bash tool

665├── settings.json # Default settings for the plugin

456├── .mcp.json # MCP server definitions666├── .mcp.json # MCP server definitions

457├── .lsp.json # LSP server configurations667├── .lsp.json # LSP server configurations

458├── scripts/ # Hook and utility scripts668├── scripts/ # Hook and utility scripts


464```674```

465 675 

466<Warning>676<Warning>

467 The `.claude-plugin/` directory contains the `plugin.json` file. All other directories (commands/, agents/, skills/, hooks/) must be at the plugin root, not inside `.claude-plugin/`.677 The `.claude-plugin/` directory contains the `plugin.json` file. All other directories (commands/, agents/, skills/, output-styles/, themes/, monitors/, hooks/) must be at the plugin root, not inside `.claude-plugin/`.

468</Warning>678</Warning>

469 679 

470### File locations reference680### File locations reference

471 681 

472| Component | Default Location | Purpose |682| Component | Default Location | Purpose |

473| :-------------- | :--------------------------- | :---------------------------------------------------------- |683| :---------------- | :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

474| **Manifest** | `.claude-plugin/plugin.json` | Required metadata file |684| **Manifest** | `.claude-plugin/plugin.json` | Plugin metadata and configuration (optional) |

475| **Commands** | `commands/` | Skill Markdown files (legacy; use `skills/` for new skills) |

476| **Agents** | `agents/` | Subagent Markdown files |

477| **Skills** | `skills/` | Skills with `<name>/SKILL.md` structure |685| **Skills** | `skills/` | Skills with `<name>/SKILL.md` structure |

686| **Commands** | `commands/` | Skills as flat Markdown files. Use `skills/` for new plugins |

687| **Agents** | `agents/` | Subagent Markdown files |

688| **Output styles** | `output-styles/` | Output style definitions |

689| **Themes** | `themes/` | Color theme definitions |

478| **Hooks** | `hooks/hooks.json` | Hook configuration |690| **Hooks** | `hooks/hooks.json` | Hook configuration |

479| **MCP servers** | `.mcp.json` | MCP server definitions |691| **MCP servers** | `.mcp.json` | MCP server definitions |

480| **LSP servers** | `.lsp.json` | Language server configurations |692| **LSP servers** | `.lsp.json` | Language server configurations |

693| **Monitors** | `monitors/monitors.json` | Background monitor configurations |

694| **Executables** | `bin/` | Executables added to the Bash tool's `PATH`. Files here are invokable as bare commands in any Bash tool call while the plugin is enabled |

695| **Settings** | `settings.json` | Default configuration applied when the plugin is enabled. Only the [`agent`](/en/sub-agents) and [`subagentStatusLine`](/en/statusline#subagent-status-lines) keys are currently supported |

481 696 

482***697***

483 698 


504| `-s, --scope <scope>` | Installation scope: `user`, `project`, or `local` | `user` |719| `-s, --scope <scope>` | Installation scope: `user`, `project`, or `local` | `user` |

505| `-h, --help` | Display help for command | |720| `-h, --help` | Display help for command | |

506 721 

722Scope determines which settings file the installed plugin is added to. For example, `--scope project` writes to `enabledPlugins` in .claude/settings.json, making the plugin available to everyone who clones the project repository.

723 

507**Examples:**724**Examples:**

508 725 

509```bash theme={null}726```bash theme={null}


532**Options:**749**Options:**

533 750 

534| Option | Description | Default |751| Option | Description | Default |

535| :-------------------- | :-------------------------------------------------- | :------ |752| :-------------------- | :---------------------------------------------------------------------------- | :------ |

536| `-s, --scope <scope>` | Uninstall from scope: `user`, `project`, or `local` | `user` |753| `-s, --scope <scope>` | Uninstall from scope: `user`, `project`, or `local` | `user` |

754| `--keep-data` | Preserve the plugin's [persistent data directory](#persistent-data-directory) | |

537| `-h, --help` | Display help for command | |755| `-h, --help` | Display help for command | |

538 756 

539**Aliases:** `remove`, `rm`757**Aliases:** `remove`, `rm`

540 758 

759By default, uninstalling from the last remaining scope also deletes the plugin's `${CLAUDE_PLUGIN_DATA}` directory. Use `--keep-data` to preserve it, for example when reinstalling after testing a new version.

760 

541### plugin enable761### plugin enable

542 762 

543Enable a disabled plugin.763Enable a disabled plugin.


597 817 

598***818***

599 819 

600## Debugging and development tools820### plugin list

601 821 

602### Debugging commands822List installed plugins with their version, source marketplace, and enable status.

603 823 

604Use `claude --debug` to see plugin loading details:824```bash theme={null}

825claude plugin list [options]

826```

827 

828**Options:**

829 

830| Option | Description | Default |

831| :------------ | :------------------------------------------------------------- | :------ |

832| `--json` | Output as JSON | |

833| `--available` | Include available plugins from marketplaces. Requires `--json` | |

834| `-h, --help` | Display help for command | |

835 

836### plugin tag

837 

838Create a release git tag for the plugin in the current directory. Run from inside the plugin's folder. See [Tag plugin releases](/en/plugin-dependencies#tag-plugin-releases-for-version-resolution).

605 839 

606```bash theme={null}840```bash theme={null}

607claude --debug841claude plugin tag [options]

608```842```

609 843 

844**Options:**

845 

846| Option | Description | Default |

847| :------------ | :------------------------------------------------------------------------- | :------ |

848| `--push` | Push the tag to the remote after creating it | |

849| `--dry-run` | Print what would be tagged without creating the tag | |

850| `-f, --force` | Create the tag even if the working tree is dirty or the tag already exists | |

851| `-h, --help` | Display help for command | |

852 

853***

854 

855## Debugging and development tools

856 

857### Debugging commands

858 

859Use `claude --debug` to see plugin loading details:

860 

610This shows:861This shows:

611 862 

612* Which plugins are being loaded863* Which plugins are being loaded

613* Any errors in plugin manifests864* Any errors in plugin manifests

614* Command, agent, and hook registration865* Skill, agent, and hook registration

615* MCP server initialization866* MCP server initialization

616 867 

617### Common issues868### Common issues

618 869 

619| Issue | Cause | Solution |870| Issue | Cause | Solution |

620| :---------------------------------- | :------------------------------ | :-------------------------------------------------------------------------------- |871| :---------------------------------- | :------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- |

621| Plugin not loading | Invalid `plugin.json` | Validate JSON syntax with `claude plugin validate` or `/plugin validate` |872| Plugin not loading | Invalid `plugin.json` | Run `claude plugin validate` or `/plugin validate` to check `plugin.json`, skill/agent/command frontmatter, and `hooks/hooks.json` for syntax and schema errors |

622| Commands not appearing | Wrong directory structure | Ensure `commands/` at root, not in `.claude-plugin/` |873| Skills not appearing | Wrong directory structure | Ensure `skills/` or `commands/` is at the plugin root, not inside `.claude-plugin/` |

623| Hooks not firing | Script not executable | Run `chmod +x script.sh` |874| Hooks not firing | Script not executable | Run `chmod +x script.sh` |

624| MCP server fails | Missing `${CLAUDE_PLUGIN_ROOT}` | Use variable for all plugin paths |875| MCP server fails | Missing `${CLAUDE_PLUGIN_ROOT}` | Use variable for all plugin paths |

625| Path errors | Absolute paths used | All paths must be relative and start with `./` |876| Path errors | Absolute paths used | All paths must be relative and start with `./` |


637 888 

638* `Warning: No commands found in plugin my-plugin custom directory: ./cmds. Expected .md files or SKILL.md in subdirectories.`: command path exists but contains no valid command files889* `Warning: No commands found in plugin my-plugin custom directory: ./cmds. Expected .md files or SKILL.md in subdirectories.`: command path exists but contains no valid command files

639* `Plugin directory not found at path: ./plugins/my-plugin. Check that the marketplace entry has the correct path.`: the `source` path in marketplace.json points to a non-existent directory890* `Plugin directory not found at path: ./plugins/my-plugin. Check that the marketplace entry has the correct path.`: the `source` path in marketplace.json points to a non-existent directory

640* `Plugin my-plugin has conflicting manifests: both plugin.json and marketplace entry specify components.`: remove duplicate component definitions or set `strict: true` in marketplace entry891* `Plugin my-plugin has conflicting manifests: both plugin.json and marketplace entry specify components.`: remove duplicate component definitions or remove `strict: false` in marketplace entry

641 892 

642### Hook troubleshooting893### Hook troubleshooting

643 894 


652 903 

6531. Verify the event name is correct (case-sensitive): `PostToolUse`, not `postToolUse`9041. Verify the event name is correct (case-sensitive): `PostToolUse`, not `postToolUse`

6542. Check the matcher pattern matches your tools: `"matcher": "Write|Edit"` for file operations9052. Check the matcher pattern matches your tools: `"matcher": "Write|Edit"` for file operations

6553. Confirm the hook type is valid: `command`, `prompt`, or `agent`9063. Confirm the hook type is valid: `command`, `http`, `mcp_tool`, `prompt`, or `agent`

656 907 

657### MCP server troubleshooting908### MCP server troubleshooting

658 909 


671 922 

672### Directory structure mistakes923### Directory structure mistakes

673 924 

674**Symptoms**: Plugin loads but components (commands, agents, hooks) are missing.925**Symptoms**: Plugin loads but components (skills, agents, hooks) are missing.

675 926 

676**Correct structure**: Components must be at the plugin root, not inside `.claude-plugin/`. Only `plugin.json` belongs in `.claude-plugin/`.927**Correct structure**: Components must be at the plugin root, not inside `.claude-plugin/`. Only `plugin.json` belongs in `.claude-plugin/`.

677 928 

678```929```text theme={null}

679my-plugin/930my-plugin/

680├── .claude-plugin/931├── .claude-plugin/

681│ └── plugin.json ← Only manifest here932│ └── plugin.json ← Only manifest here


698 949 

699### Version management950### Version management

700 951 

701Follow semantic versioning for plugin releases:952Claude Code uses the plugin's version as the cache key that determines whether an update is available. When you run `/plugin update` or auto-update fires, Claude Code computes the current version and skips the update if it matches what's already installed.

702 953 

703```json theme={null}954The version is resolved from the first of these that is set:

704{955 

705 "name": "my-plugin",9561. The `version` field in the plugin's `plugin.json`

706 "version": "2.1.0"9572. The `version` field in the plugin's marketplace entry in `marketplace.json`

707}9583. The git commit SHA of the plugin's source, for `github`, `url`, `git-subdir`, and relative-path sources in a git-hosted marketplace

708```9594. `unknown`, for `npm` sources or local directories not inside a git repository

709 960 

710**Version format**: `MAJOR.MINOR.PATCH`961This gives you two ways to version a plugin:

711 962 

712* **MAJOR**: Breaking changes (incompatible API changes)963| Approach | How | Update behavior | Best for |

713* **MINOR**: New features (backward-compatible additions)964| :--------------------- | :--------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------ |

714* **PATCH**: Bug fixes (backward-compatible fixes)965| **Explicit version** | Set `"version": "2.1.0"` in `plugin.json` | Users get updates only when you bump this field. Pushing new commits without bumping it has no effect, and `/plugin update` reports "already at the latest version". | Published plugins with stable release cycles |

966| **Commit-SHA version** | Omit `version` from both `plugin.json` and the marketplace entry | Users get updates on every new commit to the plugin's git source | Internal or team plugins under active development |

715 967 

716**Best practices**:968<Warning>

969 If you set `version` in `plugin.json`, you must bump it every time you want users to receive changes. Pushing new commits alone is not enough, because Claude Code sees the same version string and keeps the cached copy. If you're iterating quickly, leave `version` unset so the git commit SHA is used instead.

970</Warning>

717 971 

718* Start at `1.0.0` for your first stable release972If you use explicit versions, follow [semantic versioning](https://semver.org) (`MAJOR.MINOR.PATCH`): bump MAJOR for breaking changes, MINOR for new features, PATCH for bug fixes. Document changes in a `CHANGELOG.md`.

719* Update the version in `plugin.json` before distributing changes

720* Document changes in a `CHANGELOG.md` file

721* Use pre-release versions like `2.0.0-beta.1` for testing

722 973 

723***974***

724 975 

quickstart.md +43 −32

Details

6 6 

7> Welcome to Claude Code!7> Welcome to Claude Code!

8 8 

9This quickstart guide will have you using AI-powered coding assistance in just a few minutes. By the end, you'll understand how to use Claude Code for common development tasks.9 

10This quickstart guide will have you using AI-powered coding assistance in a few minutes. By the end, you'll understand how to use Claude Code for common development tasks.

11 

12 

10 13 

11## Before you begin14## Before you begin

12 15 

13Make sure you have:16Make sure you have:

14 17 

15* A terminal or command prompt open18* A terminal or command prompt open

19 * If you've never used the terminal before, check out the [terminal guide](/en/terminal-guide)

16* A code project to work with20* A code project to work with

17* A [Claude subscription](https://claude.com/pricing) (Pro, Max, Teams, or Enterprise), [Claude Console](https://console.anthropic.com/) account, or access through a [supported cloud provider](/en/third-party-integrations)21* A [Claude subscription](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=quickstart_prereq) (Pro, Max, Team, or Enterprise), [Claude Console](https://console.anthropic.com/) account, or access through a [supported cloud provider](/en/third-party-integrations)

18 22 

19<Note>23<Note>

20 This guide covers the terminal CLI. Claude Code is also available on the [web](https://claude.ai/code), as a [desktop app](/en/desktop), in [VS Code](/en/vs-code) and [JetBrains IDEs](/en/jetbrains), in [Slack](/en/slack), and in CI/CD with [GitHub Actions](/en/github-actions) and [GitLab](/en/gitlab-ci-cd). See [all interfaces](/en/overview#use-claude-code-everywhere).24 This guide covers the terminal CLI. Claude Code is also available on the [web](https://claude.ai/code), as a [desktop app](/en/desktop), in [VS Code](/en/vs-code) and [JetBrains IDEs](/en/jetbrains), in [Slack](/en/slack), and in CI/CD with [GitHub Actions](/en/github-actions) and [GitLab](/en/gitlab-ci-cd). See [all interfaces](/en/overview#use-claude-code-everywhere).


44 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd48 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd

45 ```49 ```

46 50 

51 If you see `The token '&&' is not a valid statement separator`, you're in PowerShell, not CMD. If you see `'irm' is not recognized as an internal or external command`, you're in CMD, not PowerShell. Your prompt shows `PS C:\` when you're in PowerShell and `C:\` without the `PS` when you're in CMD.

52 

53 **Native Windows setups require [Git for Windows](https://git-scm.com/downloads/win).** Install it first if you don't have it. WSL setups do not need it.

54 

47 <Info>55 <Info>

48 Native installations automatically update in the background to keep you on the latest version.56 Native installations automatically update in the background to keep you on the latest version.

49 </Info>57 </Info>

50 </Tab>58 </Tab>

51 59 

52 <Tab title="Homebrew">60 <Tab title="Homebrew">

53 ```sh theme={null}61 ```bash theme={null}

54 brew install --cask claude-code62 brew install --cask claude-code

55 ```63 ```

56 64 

65 Homebrew offers two casks. `claude-code` tracks the stable release channel, which is typically about a week behind and skips releases with major regressions. `claude-code@latest` tracks the latest channel and receives new versions as soon as they ship.

66 

57 <Info>67 <Info>

58 Homebrew installations do not auto-update. Run `brew upgrade claude-code` periodically to get the latest features and security fixes.68 Homebrew installations do not auto-update. Run `brew upgrade claude-code` or `brew upgrade claude-code@latest`, depending on which cask you installed, to get the latest features and security fixes.

59 </Info>69 </Info>

60 </Tab>70 </Tab>

61 71 


70 </Tab>80 </Tab>

71</Tabs>81</Tabs>

72 82 

83You can also install with [apt, dnf, or apk](/en/setup#install-with-linux-package-managers) on Debian, Fedora, RHEL, and Alpine.

84 

73## Step 2: Log in to your account85## Step 2: Log in to your account

74 86 

75Claude Code requires an account to use. When you start an interactive session with the `claude` command, you'll need to log in:87Claude Code requires an account to use. When you start an interactive session with the `claude` command, you'll need to log in:


86 98 

87You can log in using any of these account types:99You can log in using any of these account types:

88 100 

89* [Claude Pro, Max, Teams, or Enterprise](https://claude.com/pricing) (recommended)101* [Claude Pro, Max, Team, or Enterprise](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=quickstart_login) (recommended)

90* [Claude Console](https://console.anthropic.com/) (API access with pre-paid credits). On first login, a "Claude Code" workspace is automatically created in the Console for centralized cost tracking.102* [Claude Console](https://console.anthropic.com/) (API access with pre-paid credits). On first login, a "Claude Code" workspace is automatically created in the Console for centralized cost tracking.

91* [Amazon Bedrock, Google Vertex AI, or Microsoft Foundry](/en/third-party-integrations) (enterprise cloud providers)103* [Amazon Bedrock, Google Vertex AI, or Microsoft Foundry](/en/third-party-integrations) (enterprise cloud providers)

92 104 


104You'll see the Claude Code welcome screen with your session information, recent conversations, and latest updates. Type `/help` for available commands or `/resume` to continue a previous conversation.116You'll see the Claude Code welcome screen with your session information, recent conversations, and latest updates. Type `/help` for available commands or `/resume` to continue a previous conversation.

105 117 

106<Tip>118<Tip>

107 After logging in (Step 2), your credentials are stored on your system. Learn more in [Credential Management](/en/iam#credential-management).119 After logging in (Step 2), your credentials are stored on your system. Learn more in [Credential Management](/en/authentication#credential-management).

108</Tip>120</Tip>

109 121 

110## Step 4: Ask your first question122## Step 4: Ask your first question

111 123 

112Let's start with understanding your codebase. Try one of these commands:124Let's start with understanding your codebase. Try one of these commands:

113 125 

114```126```text theme={null}

115what does this project do?127what does this project do?

116```128```

117 129 

118Claude will analyze your files and provide a summary. You can also ask more specific questions:130Claude will analyze your files and provide a summary. You can also ask more specific questions:

119 131 

120```132```text theme={null}

121what technologies does this project use?133what technologies does this project use?

122```134```

123 135 

124```136```text theme={null}

125where is the main entry point?137where is the main entry point?

126```138```

127 139 

128```140```text theme={null}

129explain the folder structure141explain the folder structure

130```142```

131 143 

132You can also ask Claude about its own capabilities:144You can also ask Claude about its own capabilities:

133 145 

134```146```text theme={null}

135what can Claude Code do?147what can Claude Code do?

136```148```

137 149 

138```150```text theme={null}

139how do I create custom skills in Claude Code?151how do I create custom skills in Claude Code?

140```152```

141 153 

142```154```text theme={null}

143can Claude Code work with Docker?155can Claude Code work with Docker?

144```156```

145 157 

146<Note>158<Note>

147 Claude Code reads your files as needed - you don't have to manually add context. Claude also has access to its own documentation and can answer questions about its features and capabilities.159 Claude Code reads your project files as needed. You don't have to manually add context.

148</Note>160</Note>

149 161 

150## Step 5: Make your first code change162## Step 5: Make your first code change

151 163 

152Now let's make Claude Code do some actual coding. Try a simple task:164Now let's make Claude Code do some actual coding. Try a simple task:

153 165 

154```166```text theme={null}

155add a hello world function to the main file167add a hello world function to the main file

156```168```

157 169 


170 182 

171Claude Code makes Git operations conversational:183Claude Code makes Git operations conversational:

172 184 

173```185```text theme={null}

174what files have I changed?186what files have I changed?

175```187```

176 188 

177```189```text theme={null}

178commit my changes with a descriptive message190commit my changes with a descriptive message

179```191```

180 192 

181You can also prompt for more complex Git operations:193You can also prompt for more complex Git operations:

182 194 

183```195```text theme={null}

184create a new branch called feature/quickstart196create a new branch called feature/quickstart

185```197```

186 198 

187```199```text theme={null}

188show me the last 5 commits200show me the last 5 commits

189```201```

190 202 

191```203```text theme={null}

192help me resolve merge conflicts204help me resolve merge conflicts

193```205```

194 206 


198 210 

199Describe what you want in natural language:211Describe what you want in natural language:

200 212 

201```213```text theme={null}

202add input validation to the user registration form214add input validation to the user registration form

203```215```

204 216 

205Or fix existing issues:217Or fix existing issues:

206 218 

207```219```text theme={null}

208there's a bug where users can submit empty forms - fix it220there's a bug where users can submit empty forms - fix it

209```221```

210 222 


221 233 

222**Refactor code**234**Refactor code**

223 235 

224```236```text theme={null}

225refactor the authentication module to use async/await instead of callbacks237refactor the authentication module to use async/await instead of callbacks

226```238```

227 239 

228**Write tests**240**Write tests**

229 241 

230```242```text theme={null}

231write unit tests for the calculator functions243write unit tests for the calculator functions

232```244```

233 245 

234**Update documentation**246**Update documentation**

235 247 

236```248```text theme={null}

237update the README with installation instructions249update the README with installation instructions

238```250```

239 251 

240**Code review**252**Code review**

241 253 

242```254```text theme={null}

243review my changes and suggest improvements255review my changes and suggest improvements

244```256```

245 257 

246<Tip>258<Tip>

247 **Remember**: Claude Code is your AI pair programmer. Talk to it like you would a helpful colleague - describe what you want to achieve, and it will help you get there.259 Talk to Claude like you would a helpful colleague. Describe what you want to achieve, and it will help you get there.

248</Tip>260</Tip>

249 261 

250## Essential commands262## Essential commands


258| `claude -p "query"` | Run one-off query, then exit | `claude -p "explain this function"` |270| `claude -p "query"` | Run one-off query, then exit | `claude -p "explain this function"` |

259| `claude -c` | Continue most recent conversation in current directory | `claude -c` |271| `claude -c` | Continue most recent conversation in current directory | `claude -c` |

260| `claude -r` | Resume a previous conversation | `claude -r` |272| `claude -r` | Resume a previous conversation | `claude -r` |

261| `claude commit` | Create a Git commit | `claude commit` |

262| `/clear` | Clear conversation history | `/clear` |273| `/clear` | Clear conversation history | `/clear` |

263| `/help` | Show available commands | `/help` |274| `/help` | Show available commands | `/help` |

264| `exit` or Ctrl+C | Exit Claude Code | `exit` |275| `exit` or Ctrl+D | Exit Claude Code | `exit` |

265 276 

266See the [CLI reference](/en/cli-reference) for a complete list of commands.277See the [CLI reference](/en/cli-reference) for a complete list of commands.

267 278 


279 <Accordion title="Use step-by-step instructions">290 <Accordion title="Use step-by-step instructions">

280 Break complex tasks into steps:291 Break complex tasks into steps:

281 292 

282 ```293 ```text theme={null}

283 1. create a new database table for user profiles294 1. create a new database table for user profiles

284 2. create an API endpoint to get and update user profiles295 2. create an API endpoint to get and update user profiles

285 3. build a webpage that allows users to see and edit their information296 3. build a webpage that allows users to see and edit their information


289 <Accordion title="Let Claude explore first">300 <Accordion title="Let Claude explore first">

290 Before making changes, let Claude understand your code:301 Before making changes, let Claude understand your code:

291 302 

292 ```303 ```text theme={null}

293 analyze the database schema304 analyze the database schema

294 ```305 ```

295 306 

296 ```307 ```text theme={null}

297 build a dashboard showing products that are most frequently returned by our UK customers308 build a dashboard showing products that are most frequently returned by our UK customers

298 ```309 ```

299 </Accordion>310 </Accordion>

remote-control.md +259 −0 added

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# Continue local sessions from any device with Remote Control

6 

7> 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.

8 

9<Note>

10 Remote Control is in research preview and available on all plans. On Team and Enterprise, it is off by default until an admin enables the Remote Control toggle in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code).

11</Note>

12 

13Remote 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.

14 

15When you start a Remote Control session on your machine, Claude keeps running locally the entire time, so nothing moves to the cloud. With Remote Control you can:

16 

17* **Use your full local environment remotely**: your filesystem, [MCP servers](/en/mcp), tools, and project configuration all stay available, and typing `@` autocompletes file paths from your local project

18* **Work from both surfaces at once**: the conversation stays in sync across all connected devices, so you can send messages from your terminal, browser, and phone interchangeably

19* **Survive interruptions**: if your laptop sleeps or your network drops, the session reconnects automatically when your machine comes back online

20 

21Unlike [Claude Code on the web](/en/claude-code-on-the-web), which runs on cloud infrastructure, Remote Control sessions run directly on your machine and interact with your local filesystem. The web and mobile interfaces are just a window into that local session.

22 

23<Note>

24 Remote Control requires Claude Code v2.1.51 or later. Check your version with `claude --version`.

25</Note>

26 

27This page covers setup, how to start and connect to sessions, and how Remote Control compares to Claude Code on the web.

28 

29## Requirements

30 

31Before using Remote Control, confirm that your environment meets these conditions:

32 

33* **Subscription**: available on Pro, Max, Team, and Enterprise plans. API keys are not supported. On Team and Enterprise, an admin must first enable the Remote Control toggle in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code).

34* **Authentication**: run `claude` and use `/login` to sign in through claude.ai if you haven't already.

35* **Workspace trust**: run `claude` in your project directory at least once to accept the workspace trust dialog.

36 

37## Start a Remote Control session

38 

39You can start a Remote Control session from the CLI or the VS Code extension. The CLI offers three invocation modes; VS Code uses the `/remote-control` command.

40 

41<Tabs>

42 <Tab title="Server mode">

43 Navigate to your project directory and run:

44 

45 ```bash theme={null}

46 claude remote-control

47 ```

48 

49 The process stays running in your terminal in server mode, waiting for remote connections. It displays a session URL you can use to [connect from another device](#connect-from-another-device), and you can press spacebar to show a QR code for quick access from your phone. While a remote session is active, the terminal shows connection status and tool activity.

50 

51 Available flags:

52 

53 | Flag | Description |

54 | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

55 | `--name "My Project"` | Set a custom session title visible in the session list at claude.ai/code. |

56 | `--remote-control-session-name-prefix <prefix>` | Prefix for auto-generated session names when no explicit name is set. Defaults to your machine's hostname, producing names like `myhost-graceful-unicorn`. Set `CLAUDE_REMOTE_CONTROL_SESSION_NAME_PREFIX` for the same effect. |

57 | `--spawn <mode>` | How the server creates sessions.<br />• `same-dir` (default): all sessions share the current working directory, so they can conflict if editing the same files.<br />• `worktree`: each on-demand session gets its own [git worktree](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees). Requires a git repository.<br />• `session`: single-session mode. Serves exactly one session and rejects additional connections. Set at startup only.<br />Press `w` at runtime to toggle between `same-dir` and `worktree`. |

58 | `--capacity <N>` | Maximum number of concurrent sessions. Default is 32. Cannot be used with `--spawn=session`. |

59 | `--verbose` | Show detailed connection and session logs. |

60 | `--sandbox` / `--no-sandbox` | Enable or disable [sandboxing](/en/sandboxing) for filesystem and network isolation. Off by default. |

61 </Tab>

62 

63 <Tab title="Interactive session">

64 To start a normal interactive Claude Code session with Remote Control enabled, use the `--remote-control` flag (or `--rc`):

65 

66 ```bash theme={null}

67 claude --remote-control

68 ```

69 

70 Optionally pass a name for the session:

71 

72 ```bash theme={null}

73 claude --remote-control "My Project"

74 ```

75 

76 This gives you a full interactive session in your terminal that you can also control from claude.ai or the Claude app. Unlike `claude remote-control` (server mode), you can type messages locally while the session is also available remotely.

77 </Tab>

78 

79 <Tab title="From an existing session">

80 If you're already in a Claude Code session and want to continue it remotely, use the `/remote-control` (or `/rc`) command:

81 

82 ```text theme={null}

83 /remote-control

84 ```

85 

86 Pass a name as an argument to set a custom session title:

87 

88 ```text theme={null}

89 /remote-control My Project

90 ```

91 

92 This starts a Remote Control session that carries over your current conversation history and displays a session URL and QR code you can use to [connect from another device](#connect-from-another-device). The `--verbose`, `--sandbox`, and `--no-sandbox` flags are not available with this command.

93 </Tab>

94 

95 <Tab title="VS Code">

96 In the [Claude Code VS Code extension](/en/vs-code), type `/remote-control` or `/rc` in the prompt box, or open the command menu with `/` and select it. Requires Claude Code v2.1.79 or later.

97 

98 ```text theme={null}

99 /remote-control

100 ```

101 

102 A banner appears above the prompt box showing connection status. Once connected, click **Open in browser** in the banner to go directly to the session, or find it in the session list at [claude.ai/code](https://claude.ai/code). The session URL is also posted in the conversation.

103 

104 To disconnect, click the close icon on the banner or run `/remote-control` again.

105 

106 Unlike the CLI, the VS Code command does not accept a name argument or display a QR code. The session title is derived from your conversation history or first prompt.

107 </Tab>

108</Tabs>

109 

110### Connect from another device

111 

112Once a Remote Control session is active, you have a few ways to connect from another device:

113 

114* **Open the session URL** in any browser to go directly to the session on [claude.ai/code](https://claude.ai/code).

115* **Scan the QR code** shown alongside the session URL to open it directly in the Claude app. With `claude remote-control`, press spacebar to toggle the QR code display.

116* **Open [claude.ai/code](https://claude.ai/code) or the Claude app** and find the session by name in the session list. Remote Control sessions show a computer icon with a green status dot when online.

117 

118The remote session title is chosen in this order:

119 

1201. The name you passed to `--name`, `--remote-control`, or `/remote-control`

1212. The title you set with `/rename`

1223. The last meaningful message in existing conversation history

1234. An auto-generated name like `myhost-graceful-unicorn`, where `myhost` is your machine's hostname or the prefix you set with `--remote-control-session-name-prefix`

124 

125If you didn't set an explicit name, the title updates to reflect your prompt once you send one.

126 

127If the environment already has an active session, you'll be asked whether to continue it or start a new one.

128 

129If you don't have the Claude app yet, use the `/mobile` command inside Claude Code to display a download QR code for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) or [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude).

130 

131### Enable Remote Control for all sessions

132 

133By default, Remote Control only activates when you explicitly run `claude remote-control`, `claude --remote-control`, or `/remote-control`. To enable it automatically for every interactive session, run `/config` inside Claude Code and set **Enable Remote Control for all sessions** to `true`. Set it back to `false` to disable.

134 

135With this setting on, each interactive Claude Code process registers one remote session. If you run multiple instances, each one gets its own environment and session. To run multiple concurrent sessions from a single process, use [server mode](#start-a-remote-control-session) instead.

136 

137## Connection and security

138 

139Your local Claude Code session makes outbound HTTPS requests only and never opens inbound ports on your machine. When you start Remote Control, it registers with the Anthropic API and polls for work. When you connect from another device, the server routes messages between the web or mobile client and your local session over a streaming connection.

140 

141All traffic travels through the Anthropic API over TLS, the same transport security as any Claude Code session. The connection uses multiple short-lived credentials, each scoped to a single purpose and expiring independently.

142 

143## Remote Control vs Claude Code on the web

144 

145Remote Control and [Claude Code on the web](/en/claude-code-on-the-web) both use the claude.ai/code interface. The key difference is where the session runs: Remote Control executes on your machine, so your local MCP servers, tools, and project configuration stay available. Claude Code on the web executes in Anthropic-managed cloud infrastructure.

146 

147Use Remote Control when you're in the middle of local work and want to keep going from another device. Use Claude Code on the web when you want to kick off a task without any local setup, work on a repo you don't have cloned, or run multiple tasks in parallel.

148 

149## Mobile push notifications

150 

151When Remote Control is active, Claude can send push notifications to your phone.

152 

153Claude decides when to push. It typically sends one when a long-running task finishes or when it needs a decision from you to continue. You can also request a push in your prompt, for example `notify me when the tests finish`. Beyond the on/off toggle below, there is no per-event configuration.

154 

155<Note>

156 Mobile push notifications require Claude Code v2.1.110 or later.

157</Note>

158 

159To set up mobile push notifications:

160 

161<Steps>

162 <Step title="Install the Claude mobile app">

163 Download the Claude app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) or [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude).

164 </Step>

165 

166 <Step title="Sign in with your Claude Code account">

167 Use the same account and organization you use for Claude Code in the terminal.

168 </Step>

169 

170 <Step title="Allow notifications">

171 Accept the notification permission prompt from the operating system.

172 </Step>

173 

174 <Step title="Enable push in Claude Code">

175 In your terminal, run `/config` and enable **Push when Claude decides**.

176 </Step>

177</Steps>

178 

179If notifications don't arrive:

180 

181* If `/config` shows **No mobile registered**, open the Claude app on your phone so it can refresh its push token. The warning clears the next time Remote Control connects.

182* On iOS, Focus modes and notification summaries can suppress or delay pushes. Check Settings → Notifications → Claude.

183* On Android, aggressive battery optimization can delay delivery. Exempt the Claude app from battery optimization in system settings.

184 

185## Limitations

186 

187* **One remote session per interactive process**: outside of server mode, each Claude Code instance supports one remote session at a time. Use [server mode](#start-a-remote-control-session) to run multiple concurrent sessions from a single process.

188* **Local process must keep running**: Remote Control runs as a local process. If you close the terminal, quit VS Code, or otherwise stop the `claude` process, the session ends.

189* **Extended network outage**: if your machine is awake but unable to reach the network for more than roughly 10 minutes, the session times out and the process exits. Run `claude remote-control` again to start a new session.

190* **Ultraplan disconnects Remote Control**: starting an [ultraplan](/en/ultraplan) session disconnects any active Remote Control session because both features occupy the claude.ai/code interface and only one can be connected at a time.

191* **Some commands are local-only**: commands that open an interactive picker in the terminal, such as `/mcp`, `/plugin`, or `/resume`, work only from the local CLI. Commands that produce text output, including `/compact`, `/clear`, `/context`, `/usage`, `/exit`, `/extra-usage`, `/recap`, and `/reload-plugins`, work from mobile and web.

192 

193## Troubleshooting

194 

195### "Remote Control requires a claude.ai subscription"

196 

197You're not authenticated with a claude.ai account. Run `claude auth login` and choose the claude.ai option. If `ANTHROPIC_API_KEY` is set in your environment, unset it first.

198 

199### "Remote Control requires a full-scope login token"

200 

201You're authenticated with a long-lived token from `claude setup-token` or the `CLAUDE_CODE_OAUTH_TOKEN` environment variable. These tokens are limited to inference-only and cannot establish Remote Control sessions. Run `claude auth login` to authenticate with a full-scope session token instead.

202 

203### "Unable to determine your organization for Remote Control eligibility"

204 

205Your cached account information is stale or incomplete. Run `claude auth login` to refresh it.

206 

207### "Remote Control is not yet enabled for your account"

208 

209The eligibility check can fail with certain environment variables present:

210 

211* `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` or `DISABLE_TELEMETRY`: unset them and try again.

212* `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, or `CLAUDE_CODE_USE_FOUNDRY`: Remote Control requires claude.ai authentication and does not work with third-party providers.

213 

214If none of these are set, run `/logout` then `/login` to refresh.

215 

216### "Remote Control is disabled by your organization's policy"

217 

218This error has three distinct causes. Run `/status` first to see which login method and subscription you're using.

219 

220* **You're authenticated with an API key or Console account**: Remote Control requires claude.ai OAuth. Run `/login` and choose the claude.ai option. If `ANTHROPIC_API_KEY` is set in your environment, unset it.

221* **Your Team or Enterprise admin hasn't enabled it**: Remote Control is off by default on these plans. An admin can enable it at [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code) by turning on the **Remote Control** toggle. This is a server-side organization setting, not a [managed settings](/en/permissions#managed-only-settings) key.

222* **The admin toggle is grayed out**: your organization has a data retention or compliance configuration that is incompatible with Remote Control. This cannot be changed from the admin panel. Contact Anthropic support to discuss options.

223 

224### "Remote credentials fetch failed"

225 

226Claude Code could not obtain a short-lived credential from the Anthropic API to establish the connection. Re-run with `--verbose` to see the full error:

227 

228```bash theme={null}

229claude remote-control --verbose

230```

231 

232Common causes:

233 

234* Not signed in: run `claude` and use `/login` to authenticate with your claude.ai account. API key authentication is not supported for Remote Control.

235* Network or proxy issue: a firewall or proxy may be blocking the outbound HTTPS request. Remote Control requires access to the Anthropic API on port 443.

236* Session creation failed: if you also see `Session creation failed — see debug log`, the failure happened earlier in setup. Check that your subscription is active.

237 

238## Choose the right approach

239 

240Claude Code offers several ways to work when you're not at your terminal. They differ in what triggers the work, where Claude runs, and how much you need to set up.

241 

242| | Trigger | Claude runs on | Setup | Best for |

243| :--------------------------------------------- | :--------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------ |

244| [Dispatch](/en/desktop#sessions-from-dispatch) | Message a task from the Claude mobile app | Your machine (Desktop) | [Pair the mobile app with Desktop](https://support.claude.com/en/articles/13947068) | Delegating work while you're away, minimal setup |

245| [Remote Control](/en/remote-control) | Drive a running session from [claude.ai/code](https://claude.ai/code) or the Claude mobile app | Your machine (CLI or VS Code) | Run `claude remote-control` | Steering in-progress work from another device |

246| [Channels](/en/channels) | Push events from a chat app like Telegram or Discord, or your own server | Your machine (CLI) | [Install a channel plugin](/en/channels#quickstart) or [build your own](/en/channels-reference) | Reacting to external events like CI failures or chat messages |

247| [Slack](/en/slack) | Mention `@Claude` in a team channel | Anthropic cloud | [Install the Slack app](/en/slack#setting-up-claude-code-in-slack) with [Claude Code on the web](/en/claude-code-on-the-web) enabled | PRs and reviews from team chat |

248| [Scheduled tasks](/en/scheduled-tasks) | Set a schedule | [CLI](/en/scheduled-tasks), [Desktop](/en/desktop-scheduled-tasks), or [cloud](/en/routines) | Pick a frequency | Recurring automation like daily reviews |

249 

250## Related resources

251 

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

253* [Ultraplan](/en/ultraplan): launch a cloud planning session from your terminal and review the plan in your browser

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

255* [Dispatch](/en/desktop#sessions-from-dispatch): message a task from your phone and it can spawn a Desktop session to handle it

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

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

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

259* [Data usage](/en/data-usage): what data flows through the Anthropic API during local and remote sessions

routines.md +337 −0 added

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# Automate work with routines

6 

7> Put Claude Code on autopilot. Define routines that run on a schedule, trigger on API calls, or react to GitHub events from Anthropic-managed cloud infrastructure.

8 

9<Note>

10 Routines are in research preview. Behavior, limits, and the API surface may change.

11</Note>

12 

13A routine is a saved Claude Code configuration: a prompt, one or more repositories, and a set of [connectors](/en/mcp), packaged once and run automatically. Routines execute on Anthropic-managed cloud infrastructure, so they keep working when your laptop is closed.

14 

15Each routine can have one or more triggers attached to it:

16 

17* **Scheduled**: run on a recurring cadence like hourly, nightly, or weekly, or once at a specific future time

18* **API**: trigger on demand by sending an HTTP POST to a per-routine endpoint with a bearer token

19* **GitHub**: run automatically in response to repository events such as pull requests or releases

20 

21A single routine can combine triggers. For example, a PR review routine can run nightly, trigger from a deploy script, and also react to every new PR.

22 

23Routines are available on Pro, Max, Team, and Enterprise plans with [Claude Code on the web](/en/claude-code-on-the-web) enabled. Create and manage them at [claude.ai/code/routines](https://claude.ai/code/routines), or from the CLI with `/schedule`.

24 

25This page covers creating a routine, configuring each trigger type, managing runs, and how usage limits apply.

26 

27## Example use cases

28 

29Each example pairs a trigger type with the kind of work routines are suited to: unattended, repeatable, and tied to a clear outcome.

30 

31**Backlog maintenance.** A schedule trigger runs every weeknight against your issue tracker via a connector. The routine reads issues opened since the last run, applies labels, assigns owners based on the area of code referenced, and posts a summary to Slack so the team starts the day with a groomed queue.

32 

33**Alert triage.** Your monitoring tool calls the routine's API endpoint when an error threshold is crossed, passing the alert body as `text`. The routine pulls the stack trace, correlates it with recent commits in the repository, and opens a draft pull request with a proposed fix and a link back to the alert. On-call reviews the PR instead of starting from a blank terminal.

34 

35**Bespoke code review.** A GitHub trigger runs on `pull_request.opened`. The routine applies your team's own review checklist, leaves inline comments for security, performance, and style issues, and adds a summary comment so human reviewers can focus on design instead of mechanical checks.

36 

37**Deploy verification.** Your CD pipeline calls the routine's API endpoint after each production deploy. The routine runs smoke checks against the new build, scans error logs for regressions, and posts a go or no-go to the release channel before the deploy window closes.

38 

39**Docs drift.** A schedule trigger runs weekly. The routine scans merged PRs since the last run, flags documentation that references changed APIs, and opens update PRs against the docs repository for an editor to review.

40 

41**Library port.** A GitHub trigger runs on `pull_request.closed` filtered to merged PRs in one SDK repository. The routine ports the change to a parallel SDK in another language and opens a matching PR, keeping the two libraries in step without a human re-implementing each change.

42 

43The sections below walk through creating a routine and configuring each of these trigger types.

44 

45## Create a routine

46 

47Create a routine from the web at [claude.ai/code/routines](https://claude.ai/code/routines), from the Desktop app, or from the CLI. All three surfaces write to the same cloud account, so a routine you create in one shows up in the others immediately. In the Desktop app, click **Routines** in the sidebar, then **New routine**, and choose **Remote**; choosing **Local** instead creates a [Desktop scheduled task](/en/desktop-scheduled-tasks), which runs on your machine rather than in the cloud.

48 

49The creation form sets up the routine's prompt, repositories, environment, connectors, and triggers.

50 

51Routines run autonomously as full Claude Code cloud sessions: there is no permission-mode picker and no approval prompts during a run. The session can run shell commands, use [skills](/en/skills) committed to the cloned repository, and call any connectors you include. What a routine can reach is determined by the repositories you select and their branch-push setting, the [environment's](/en/claude-code-on-the-web#the-cloud-environment) network access and variables, and the connectors you include. Scope each of those to what the routine actually needs.

52 

53Routines belong to your individual claude.ai account. They are not shared with teammates, and they count against your account's daily run allowance. Anything a routine does through your connected GitHub identity or connectors appears as you: commits and pull requests carry your GitHub user, and Slack messages, Linear tickets, or other connector actions use your linked accounts for those services.

54 

55### Create from the web

56 

57<Steps>

58 <Step title="Open the creation form">

59 Visit [claude.ai/code/routines](https://claude.ai/code/routines) and click **New routine**.

60 </Step>

61 

62 <Step title="Name the routine and write the prompt">

63 Give the routine a descriptive name and write the prompt Claude runs each time. The prompt is the most important part: the routine runs autonomously, so the prompt must be self-contained and explicit about what to do and what success looks like.

64 

65 The prompt input includes a model selector. Claude uses the selected model on every run.

66 </Step>

67 

68 <Step title="Select repositories">

69 Add one or more GitHub repositories for Claude to work in. Each repository is cloned at the start of a run, starting from the default branch. Claude creates `claude/`-prefixed branches for its changes.

70 </Step>

71 

72 <Step title="Select an environment">

73 Pick a [cloud environment](/en/claude-code-on-the-web#the-cloud-environment) for the routine. Environments control what the cloud session has access to:

74 

75 * **Network access**: set the level of internet access available during each run

76 * **Environment variables**: provide API keys, tokens, or other secrets Claude can use

77 * **Setup script**: install dependencies and tools the routine needs. The result is [cached](/en/claude-code-on-the-web#environment-caching), so the script doesn't re-run on every session

78 

79 A **Default** environment is provided. To use a custom environment, [create one](/en/claude-code-on-the-web#the-cloud-environment) before creating the routine.

80 </Step>

81 

82 <Step title="Select a trigger">

83 Under **Select a trigger**, choose how the routine starts. You can pick one trigger type or combine several.

84 

85 <Tabs>

86 <Tab title="Schedule">

87 Pick a preset frequency for a recurring run, or schedule a single one-off run at a specific timestamp. See [Add a schedule trigger](#add-a-schedule-trigger) for timezone handling, stagger, custom cron intervals, and one-off runs.

88 </Tab>

89 

90 <Tab title="GitHub event">

91 Select the repository, the event to react to, and optional filters. See [Add a GitHub trigger](#add-a-github-trigger) for the full list of supported events and filter fields.

92 </Tab>

93 

94 <Tab title="API">

95 Select **API** here, then save the routine. The URL and token are generated after the routine is saved, since they depend on the routine ID. See [Add an API trigger](#add-an-api-trigger) to copy the URL and generate a token.

96 </Tab>

97 </Tabs>

98 </Step>

99 

100 <Step title="Review connectors and permissions">

101 The **Connectors** and **Permissions** tabs at the bottom of the form control what the routine can reach.

102 

103 Under Connectors, all of your connected [MCP connectors](/en/mcp) are included by default. Remove any the routine doesn't need. Claude can use every tool from an included connector, including writes, without asking for permission during a run.

104 

105 Under Permissions, enable **Allow unrestricted branch pushes** for any repository where Claude should be able to push to existing branches instead of only `claude/`-prefixed ones.

106 </Step>

107 

108 <Step title="Create the routine">

109 Click **Create**. The routine appears in the list and runs the next time one of its triggers matches. To start a run immediately, click **Run now** on the routine's detail page.

110 

111 Each run creates a new session alongside your other sessions, where you can see what Claude did, review changes, and create a pull request.

112 </Step>

113</Steps>

114 

115### Create from the CLI

116 

117Run `/schedule` in any session to create a scheduled routine conversationally. You can also pass a description directly, for a recurring routine like `/schedule daily PR review at 9am` or a one-off like `/schedule clean up feature flag in one week`. Claude walks through the same information the web form collects, then saves the routine to your account.

118 

119`/schedule` in the CLI creates scheduled routines only. To add an API or GitHub trigger, edit the routine on the web at [claude.ai/code/routines](https://claude.ai/code/routines).

120 

121The CLI also supports managing existing routines. Run `/schedule list` to see all routines, `/schedule update` to change one, or `/schedule run` to trigger it immediately.

122 

123## Configure triggers

124 

125A routine starts when one of its triggers matches. You can attach any combination of schedule, API, and GitHub triggers to the same routine, and add or remove them at any time from the **Select a trigger** section of the routine's edit form.

126 

127### Add a schedule trigger

128 

129A schedule trigger runs the routine on a recurring cadence, or once at a specific future time. Pick a preset frequency in the **Select a trigger** section: hourly, daily, weekdays, or weekly. Times are entered in your local zone and converted automatically, so the routine runs at that wall-clock time regardless of where the cloud infrastructure is located.

130 

131Runs may start a few minutes after the scheduled time due to stagger. The offset is consistent for each routine.

132 

133For a custom interval such as every two hours or the first of each month, pick the closest preset in the form, then run `/schedule update` in the CLI to set a specific cron expression. The minimum interval is one hour; expressions that run more frequently are rejected.

134 

135#### Schedule a one-off run

136 

137A one-off schedule fires the routine a single time at a specific timestamp. Use it to remind yourself later in the week, to open a cleanup PR after a rollout finishes, or to kick off a follow-up task when an upstream change lands. After the routine fires, it auto-disables and the web UI marks it as **Ran**. To run it again, edit the routine and set a new one-off time.

138 

139Create a one-off run from the CLI by describing the time in natural language. Claude resolves the phrase against the current time and confirms the absolute timestamp before saving.

140 

141```text theme={null}

142/schedule tomorrow at 9am, summarize yesterday's merged PRs

143```

144 

145```text theme={null}

146/schedule in 2 weeks, open a cleanup PR that removes the feature flag

147```

148 

149The same local-to-UTC conversion as recurring schedules applies to one-off timestamps.

150 

151One-off runs do not count against the daily routine run cap. They consume your plan's regular subscription usage like any other session. See [Usage and limits](#usage-and-limits) for details.

152 

153### Add an API trigger

154 

155An API trigger gives a routine a dedicated HTTP endpoint. POSTing to the endpoint with the routine's bearer token starts a new session and returns a session URL. Use this to wire Claude Code into alerting systems, deploy pipelines, internal tools, or anywhere you can make an authenticated HTTP request.

156 

157API triggers are added to an existing routine from the web. The CLI cannot currently create or revoke tokens.

158 

159<Steps>

160 <Step title="Open the routine for editing">

161 Go to [claude.ai/code/routines](https://claude.ai/code/routines), click the routine you want to trigger via API, then click the pencil icon to open **Edit routine**.

162 </Step>

163 

164 <Step title="Add an API trigger">

165 Scroll to the **Select a trigger** section below the prompt, click **Add another trigger**, and choose **API**.

166 </Step>

167 

168 <Step title="Copy the URL and generate a token">

169 The modal shows the URL for this routine along with a sample curl command. Copy the URL, then click **Generate token** and copy the token immediately. The token is shown once and cannot be retrieved later, so store it somewhere secure such as your alerting tool's secret store.

170 </Step>

171 

172 <Step title="Call the endpoint">

173 Send the token in the `Authorization: Bearer` header when you POST to the URL. The [Trigger a routine](#trigger-a-routine) section below shows a complete example.

174 </Step>

175</Steps>

176 

177Each routine has its own token, scoped to triggering that routine only. To rotate or revoke it, return to the same modal and click **Regenerate** or **Revoke**.

178 

179#### Trigger a routine

180 

181Send a POST request to the `/fire` endpoint with the bearer token in the `Authorization` header. The request body accepts an optional `text` field for run-specific context such as an alert body or a failing log, passed to the routine alongside its saved prompt. The value is freeform text and is not parsed: if you send JSON or another structured payload, the routine receives it as a literal string.

182 

183The example below triggers a routine from a shell:

184 

185```bash theme={null}

186curl -X POST https://api.anthropic.com/v1/claude_code/routines/trig_01ABCDEFGHJKLMNOPQRSTUVW/fire \

187 -H "Authorization: Bearer sk-ant-oat01-xxxxx" \

188 -H "anthropic-beta: experimental-cc-routine-2026-04-01" \

189 -H "anthropic-version: 2023-06-01" \

190 -H "Content-Type: application/json" \

191 -d '{"text": "Sentry alert SEN-4521 fired in prod. Stack trace attached."}'

192```

193 

194A successful request returns a JSON body with the new session ID and URL:

195 

196```json theme={null}

197{

198 "type": "routine_fire",

199 "claude_code_session_id": "session_01HJKLMNOPQRSTUVWXYZ",

200 "claude_code_session_url": "https://claude.ai/code/session_01HJKLMNOPQRSTUVWXYZ"

201}

202```

203 

204Open the session URL in a browser to watch the run in real time, review changes, or continue the conversation manually.

205 

206<Warning>

207 The `/fire` endpoint ships under the `experimental-cc-routine-2026-04-01` beta header. Request and response shapes, rate limits, and token semantics may change while the feature is in research preview. Breaking changes ship behind new dated beta header versions, and the two most recent previous header versions continue to work so that callers have time to migrate.

208</Warning>

209 

210#### API reference

211 

212For the full API reference, including all error responses, validation rules, and field limits, see [Trigger a routine via API](https://platform.claude.com/docs/en/api/claude-code/routines-fire) in the Claude Platform documentation.

213 

214The `/fire` endpoint is available to claude.ai users only and is not part of the Claude Platform API surface.

215 

216### Add a GitHub trigger

217 

218A GitHub trigger starts a new session automatically when a matching event occurs on a connected repository. Each matching event starts its own session.

219 

220<Note>

221 During the research preview, GitHub webhook events are subject to per-routine and per-account hourly caps. Events beyond the limit are dropped until the window resets. See your current limits at [claude.ai/code/routines](https://claude.ai/code/routines).

222</Note>

223 

224GitHub triggers are configured from the web UI only.

225 

226<Steps>

227 <Step title="Open the routine for editing">

228 Go to [claude.ai/code/routines](https://claude.ai/code/routines), click the routine, then click the pencil icon to open **Edit routine**.

229 </Step>

230 

231 <Step title="Add a GitHub event trigger">

232 Scroll to the **Select a trigger** section, click **Add another trigger**, and choose **GitHub event**.

233 </Step>

234 

235 <Step title="Install the Claude GitHub App">

236 The Claude GitHub App must be installed on the repository you want to subscribe to. The trigger setup prompts you to install it if it isn't already.

237 

238 <Note>

239 Running `/web-setup` in the CLI grants repository access for cloning, but it does not install the Claude GitHub App and does not enable webhook delivery. GitHub triggers require installing the Claude GitHub App, which the trigger setup prompts you to do.

240 </Note>

241 </Step>

242 

243 <Step title="Configure the trigger">

244 Select the repository, choose an event from the [supported events](#supported-events) list, and optionally add filters. Save the trigger.

245 </Step>

246</Steps>

247 

248#### Supported events

249 

250GitHub triggers can subscribe to either of the following event categories. Within each category you can pick a specific action, such as `pull_request.opened`, or react to all actions in the category.

251 

252| Event | Triggers when |

253| :----------- | :---------------------------------------------------------------------------- |

254| Pull request | A PR is opened, closed, assigned, labeled, synchronized, or otherwise updated |

255| Release | A release is created, published, edited, or deleted |

256 

257#### Filter pull requests

258 

259Use filters to narrow which pull requests start a new session. All filter conditions must match for the routine to trigger. The available filter fields are:

260 

261| Filter | Matches |

262| :---------- | :------------------------------- |

263| Author | PR author's GitHub username |

264| Title | PR title text |

265| Body | PR description text |

266| Base branch | Branch the PR targets |

267| Head branch | Branch the PR comes from |

268| Labels | Labels applied to the PR |

269| Is draft | Whether the PR is in draft state |

270| Is merged | Whether the PR has been merged |

271 

272Each filter pairs a field with an operator: equals, contains, starts with, is one of, is not one of, or matches regex.

273 

274The `matches regex` operator tests the entire field value, not a substring within it. To match any title containing `hotfix`, write `.*hotfix.*`. Without the surrounding `.*`, the filter matches only a title that is exactly `hotfix` with nothing before or after. For literal substring matching without regex syntax, use the `contains` operator instead.

275 

276A few example filter combinations:

277 

278* **Auth module review**: base branch `main`, head branch contains `auth-provider`. Sends any PR that touches authentication to a focused reviewer.

279* **Ready-for-review only**: is draft is `false`. Skips drafts so the routine only runs when the PR is ready for review.

280* **Label-gated backport**: labels include `needs-backport`. Triggers a port-to-another-branch routine only when a maintainer tags the PR.

281 

282#### How sessions map to events

283 

284Each matching GitHub event starts a new session. Session reuse across events is not available for GitHub-triggered routines, so two PR updates produce two independent sessions.

285 

286## Manage routines

287 

288Click a routine in the list to open its detail page. The detail page shows the routine's repositories, connectors, prompt, schedule, API tokens, GitHub triggers, and a list of past runs.

289 

290### View and interact with runs

291 

292Click any run to open it as a full session. From there you can see what Claude did, review changes, create a pull request, or continue the conversation. Each run session works like any other session: use the dropdown menu next to the session title to rename, archive, or delete it.

293 

294### Edit and control routines

295 

296From the routine detail page you can:

297 

298* Click **Run now** to start a run immediately without waiting for the next scheduled time.

299* Use the toggle in the **Repeats** section to pause or resume the schedule. Paused routines keep their configuration but don't run until you re-enable them.

300* Click the pencil icon to open **Edit routine** and change the name, prompt, repositories, environment, connectors, or any of the routine's triggers. The **Select a trigger** section is where you add or remove schedules, API tokens, and GitHub event triggers.

301* Click the delete icon to remove the routine. Past sessions created by the routine remain in your session list.

302 

303### Repositories and branch permissions

304 

305Routines need GitHub access to clone repositories. When you create a routine from the CLI with `/schedule`, Claude checks whether your account has GitHub connected and prompts you to run `/web-setup` if it doesn't. See [GitHub authentication options](/en/claude-code-on-the-web#github-authentication-options) for the two ways to grant access.

306 

307Each repository you add is cloned on every run. Claude starts from the repository's default branch unless your prompt specifies otherwise.

308 

309By default, Claude can only push to branches prefixed with `claude/`. This prevents routines from accidentally modifying protected or long-lived branches. To remove this restriction for a specific repository, enable **Allow unrestricted branch pushes** for that repository when creating or editing the routine.

310 

311### Connectors

312 

313Routines can use your connected MCP connectors to read from and write to external services during each run. For example, a routine that triages support requests might read from a Slack channel and create issues in Linear.

314 

315When you create a routine, all of your currently connected connectors are included by default. Remove any that aren't needed to limit which tools Claude has access to during the run. You can also add connectors directly from the routine form.

316 

317To manage or add connectors outside of the routine form, visit **Settings > Connectors** on claude.ai or use `/schedule update` in the CLI.

318 

319### Environments

320 

321Each routine runs in a [cloud environment](/en/claude-code-on-the-web#the-cloud-environment) that controls network access, environment variables, and setup scripts. Configure environments before creating a routine to give Claude access to APIs, install dependencies, or restrict network scope. See [cloud environment](/en/claude-code-on-the-web#the-cloud-environment) for the full setup guide.

322 

323## Usage and limits

324 

325Routines draw down subscription usage the same way interactive sessions do. In addition to the standard subscription limits, routines have a daily cap on how many runs can start per account. See your current consumption and remaining daily routine runs at [claude.ai/code/routines](https://claude.ai/code/routines) or [claude.ai/settings/usage](https://claude.ai/settings/usage).

326 

327When a routine hits the daily cap or your subscription usage limit, organizations with extra usage enabled can keep running routines on metered overage. Without extra usage, additional runs are rejected until the window resets. Enable extra usage from **Settings > Billing** on claude.ai.

328 

329One-off runs do not count against the daily routine cap. They draw down your regular subscription usage like any other session, but they are exempt from the per-account daily routine run allowance.

330 

331## Related resources

332 

333* [`/loop` and in-session scheduling](/en/scheduled-tasks): schedule local tasks within an open CLI session

334* [Desktop scheduled tasks](/en/desktop-scheduled-tasks): local scheduled tasks that run on your machine with access to local files

335* [Cloud environment](/en/claude-code-on-the-web#the-cloud-environment): configure the runtime environment for cloud sessions

336* [MCP connectors](/en/mcp): connect external services like Slack, Linear, and Google Drive

337* [GitHub Actions](/en/github-actions): run Claude in your CI pipeline on repository events

sandboxing.md +88 −9

Details

42* **Blocked access**: Cannot modify files outside the current working directory without explicit permission42* **Blocked access**: Cannot modify files outside the current working directory without explicit permission

43* **Configurable**: Define custom allowed and denied paths through settings43* **Configurable**: Define custom allowed and denied paths through settings

44 44 

45You can grant write access to additional paths using `sandbox.filesystem.allowWrite` in your settings. These restrictions are enforced at the OS level (Seatbelt on macOS, bubblewrap on Linux), so they apply to all subprocess commands, including tools like `kubectl`, `terraform`, and `npm`, not just Claude's file tools.

46 

45### Network isolation47### Network isolation

46 48 

47Network access is controlled through a proxy server running outside the sandbox:49Network access is controlled through a proxy server running outside the sandbox:

48 50 

49* **Domain restrictions**: Only approved domains can be accessed51* **Domain restrictions**: Only approved domains can be accessed

50* **User confirmation**: New domain requests trigger permission prompts52* **User confirmation**: New domain requests trigger permission prompts (unless [`allowManagedDomainsOnly`](/en/settings#sandbox-settings) is enabled, which blocks non-allowed domains automatically)

51* **Custom proxy support**: Advanced users can implement custom rules on outgoing traffic53* **Custom proxy support**: Advanced users can implement custom rules on outgoing traffic

52* **Comprehensive coverage**: Restrictions apply to all scripts, programs, and subprocesses spawned by commands54* **Comprehensive coverage**: Restrictions apply to all scripts, programs, and subprocesses spawned by commands

53 55 


89 91 

90You can enable sandboxing by running the `/sandbox` command:92You can enable sandboxing by running the `/sandbox` command:

91 93 

92```94```text theme={null}

93> /sandbox95/sandbox

94```96```

95 97 

96This opens a menu where you can choose between sandbox modes. If required dependencies are missing (such as `bubblewrap` or `socat` on Linux), the menu displays installation instructions for your platform.98This opens a menu where you can choose between sandbox modes. If required dependencies are missing (such as `bubblewrap` or `socat` on Linux), the menu displays installation instructions for your platform.

97 99 

100By default, if the sandbox cannot start (missing dependencies or unsupported platform), Claude Code shows a warning and runs commands without sandboxing. To make this a hard failure instead, set [`sandbox.failIfUnavailable`](/en/settings#sandbox-settings) to `true`. This is intended for managed deployments that require sandboxing as a security gate.

101 

98### Sandbox modes102### Sandbox modes

99 103 

100Claude Code offers two sandbox modes:104Claude Code offers two sandbox modes:

101 105 

102**Auto-allow mode**: Bash commands will attempt to run inside the sandbox and are automatically allowed without requiring permission. Commands that cannot be sandboxed (such as those needing network access to non-allowed hosts) fall back to the regular permission flow. Explicit ask/deny rules you've configured are always respected.106**Auto-allow mode**: Bash commands will attempt to run inside the sandbox and are automatically allowed without requiring permission. Commands that cannot be sandboxed (such as those needing network access to non-allowed hosts) fall back to the regular permission flow. Explicit deny rules are always respected, and `rm` or `rmdir` commands that target `/`, your home directory, or other critical system paths still trigger a permission prompt. Ask rules apply only to commands that fall back to the regular permission flow.

103 107 

104**Regular permissions mode**: All bash commands go through the standard permission flow, even when sandboxed. This provides more control but requires more approvals.108**Regular permissions mode**: All bash commands go through the standard permission flow, even when sandboxed. This provides more control but requires more approvals.

105 109 


113 117 

114Customize sandbox behavior through your `settings.json` file. See [Settings](/en/settings#sandbox-settings) for complete configuration reference.118Customize sandbox behavior through your `settings.json` file. See [Settings](/en/settings#sandbox-settings) for complete configuration reference.

115 119 

120#### Granting subprocess write access to specific paths

121 

122By default, sandboxed commands can only write to the current working directory. If subprocess commands like `kubectl`, `terraform`, or `npm` need to write outside the project directory, use `sandbox.filesystem.allowWrite` to grant access to specific paths:

123 

124```json theme={null}

125{

126 "sandbox": {

127 "enabled": true,

128 "filesystem": {

129 "allowWrite": ["~/.kube", "/tmp/build"]

130 }

131 }

132}

133```

134 

135These paths are enforced at the OS level, so all commands running inside the sandbox, including their child processes, respect them. This is the recommended approach when a tool needs write access to a specific location, rather than excluding the tool from the sandbox entirely with `excludedCommands`.

136 

137When `allowWrite` (or `denyWrite`/`denyRead`/`allowRead`) is defined in multiple [settings scopes](/en/settings#settings-precedence), the arrays are **merged**, meaning paths from every scope are combined, not replaced. For example, if managed settings allow writes to `/opt/company-tools` and a user adds `~/.kube` in their personal settings, both paths are included in the final sandbox configuration. This means users and projects can extend the list without duplicating or overriding paths set by higher-priority scopes.

138 

139Path prefixes control how paths are resolved:

140 

141| Prefix | Meaning | Example |

142| :---------------- | :------------------------------------------------------------------------------------- | :------------------------------------------------------------------------ |

143| `/` | Absolute path from filesystem root | `/tmp/build` stays `/tmp/build` |

144| `~/` | Relative to home directory | `~/.kube` becomes `$HOME/.kube` |

145| `./` or no prefix | Relative to the project root for project settings, or to `~/.claude` for user settings | `./output` in `.claude/settings.json` resolves to `<project-root>/output` |

146 

147The older `//path` prefix for absolute paths still works. If you previously used single-slash `/path` expecting project-relative resolution, switch to `./path`. This syntax differs from [Read and Edit permission rules](/en/permissions#read-and-edit), which use `//path` for absolute and `/path` for project-relative. Sandbox filesystem paths use standard conventions: `/tmp/build` is an absolute path.

148 

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

150 

151For 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`:

152 

153```json theme={null}

154{

155 "sandbox": {

156 "enabled": true,

157 "filesystem": {

158 "denyRead": ["~/"],

159 "allowRead": ["."]

160 }

161 }

162}

163```

164 

165The `.` 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.

166 

116<Tip>167<Tip>

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

118 169 

119 * Many CLI tools require accessing certain hosts. As you use these tools, they will request permission to access certain hosts. Granting permission will allow them to access these hosts now and in the future, enabling them to safely execute inside the sandbox.170 * Many CLI tools require accessing certain hosts. As you use these tools, they will request permission to access certain hosts. Granting permission will allow them to access these hosts now and in the future, enabling them to safely execute inside the sandbox.

120 * `watchman` is incompatible with running in the sandbox. If you're running `jest`, consider using `jest --no-watchman`171 * `watchman` is incompatible with running in the sandbox. If you're running `jest`, consider using `jest --no-watchman`

121 * `docker` is incompatible with running in the sandbox. Consider specifying `docker` in `excludedCommands` to force it to run outside of the sandbox.172 * `docker` is incompatible with running in the sandbox. Consider specifying `docker *` in `excludedCommands` to force it to run outside of the sandbox.

122</Tip>173</Tip>

123 174 

124<Note>175<Note>


137 188 

138* Cannot modify critical config files such as `~/.bashrc`189* Cannot modify critical config files such as `~/.bashrc`

139* Cannot modify system-level files in `/bin/`190* Cannot modify system-level files in `/bin/`

140* Cannot read files that are denied in your [Claude permission settings](/en/iam#configuring-permissions)191* Cannot read files that are denied in your [Claude permission settings](/en/permissions#manage-permissions)

141 192 

142**Network protection:**193**Network protection:**

143 194 


184* Filesystem Permission Escalation: Overly broad filesystem write permissions can enable privilege escalation attacks. Allowing writes to directories containing executables in `$PATH`, system configuration directories, or user shell configuration files (`.bashrc`, `.zshrc`) can lead to code execution in different security contexts when other users or system processes access these files.235* Filesystem Permission Escalation: Overly broad filesystem write permissions can enable privilege escalation attacks. Allowing writes to directories containing executables in `$PATH`, system configuration directories, or user shell configuration files (`.bashrc`, `.zshrc`) can lead to code execution in different security contexts when other users or system processes access these files.

185* Linux Sandbox Strength: The Linux implementation provides strong filesystem and network isolation but includes an `enableWeakerNestedSandbox` mode that enables it to work inside of Docker environments without privileged namespaces. This option considerably weakens security and should only be used in cases where additional isolation is otherwise enforced.236* Linux Sandbox Strength: The Linux implementation provides strong filesystem and network isolation but includes an `enableWeakerNestedSandbox` mode that enables it to work inside of Docker environments without privileged namespaces. This option considerably weakens security and should only be used in cases where additional isolation is otherwise enforced.

186 237 

238## How sandboxing relates to permissions

239 

240Sandboxing and [permissions](/en/permissions) are complementary security layers that work together:

241 

242* **Permissions** control which tools Claude Code can use and are evaluated before any tool runs. They apply to all tools: Bash, Read, Edit, WebFetch, MCP, and others.

243* **Sandboxing** provides OS-level enforcement that restricts what Bash commands can access at the filesystem and network level. It applies only to Bash commands and their child processes.

244 

245Filesystem and network restrictions are configured through both sandbox settings and permission rules:

246 

247* Use `sandbox.filesystem.allowWrite` to grant subprocess write access to paths outside the working directory

248* Use `sandbox.filesystem.denyWrite` and `sandbox.filesystem.denyRead` to block subprocess access to specific paths

249* Use `sandbox.filesystem.allowRead` to re-allow reading specific paths within a `denyRead` region

250* Use `Read` and `Edit` deny rules to block access to specific files or directories

251* Use `WebFetch` allow/deny rules to control domain access

252* Use sandbox `allowedDomains` to control which domains Bash commands can reach

253* Use sandbox `deniedDomains` to block specific domains even when a broader `allowedDomains` wildcard would otherwise permit them

254 

255Paths from both `sandbox.filesystem` settings and permission rules are merged together into the final sandbox configuration.

256 

257This [repository](https://github.com/anthropics/claude-code/tree/main/examples/settings) includes starter settings configurations for common deployment scenarios, including sandbox-specific examples. Use these as starting points and adjust them to fit your needs.

258 

187## Advanced usage259## Advanced usage

188 260 

189### Custom proxy configuration261### Custom proxy configuration


210 282 

211The sandboxed bash tool works alongside:283The sandboxed bash tool works alongside:

212 284 

213* **IAM policies**: Combine with [permission settings](/en/iam) for defense-in-depth285* **Permission rules**: Combine with [permission settings](/en/permissions) for defense-in-depth

214* **Development containers**: Use with [devcontainers](/en/devcontainer) for additional isolation286* **Development containers**: Use with [dev containers](/en/devcontainer) for additional isolation

215* **Enterprise policies**: Enforce sandbox configurations through [managed settings](/en/settings#settings-precedence)287* **Enterprise policies**: Enforce sandbox configurations through [managed settings](/en/settings#settings-precedence)

216 288 

217## Best practices289## Best practices


238* **Compatibility**: Some tools that require specific system access patterns may need configuration adjustments, or may even need to be run outside of the sandbox310* **Compatibility**: Some tools that require specific system access patterns may need configuration adjustments, or may even need to be run outside of the sandbox

239* **Platform support**: Supports macOS, Linux, and WSL2. WSL1 is not supported. Native Windows support is planned.311* **Platform support**: Supports macOS, Linux, and WSL2. WSL1 is not supported. Native Windows support is planned.

240 312 

313## What sandboxing does not cover

314 

315The sandbox isolates Bash subprocesses. Other tools operate under different boundaries:

316 

317* **Built-in file tools**: Read, Edit, and Write use the permission system directly rather than running through the sandbox. See [permissions](/en/permissions).

318* **Computer use**: when Claude opens apps and controls your screen, it runs on your actual desktop rather than in an isolated environment. Per-app permission prompts gate each application. See [computer use in the CLI](/en/computer-use) or [computer use in Desktop](/en/desktop#let-claude-use-your-computer).

319 

241## See also320## See also

242 321 

243* [Security](/en/security) - Comprehensive security features and best practices322* [Security](/en/security) - Comprehensive security features and best practices

244* [IAM](/en/iam) - Permission configuration and access control323* [Permissions](/en/permissions) - Permission configuration and access control

245* [Settings](/en/settings) - Complete configuration reference324* [Settings](/en/settings) - Complete configuration reference

246* [CLI reference](/en/cli-reference) - Command-line options325* [CLI reference](/en/cli-reference) - Command-line options

scheduled-tasks.md +213 −0 added

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# Run prompts on a schedule

6 

7> Use /loop and the cron scheduling tools to run prompts repeatedly, poll for status, or set one-time reminders within a Claude Code session.

8 

9<Note>

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

11</Note>

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. 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 

15Tasks are session-scoped: they live in the current conversation and stop when you start a new one. Resuming with `--resume` or `--continue` brings back any task that hasn't [expired](#seven-day-expiry): a recurring task created within the last 7 days, or a one-shot whose scheduled time hasn't passed yet. For scheduling that survives independently of any session, use [Routines](/en/routines), [Desktop scheduled tasks](/en/desktop-scheduled-tasks), or [GitHub Actions](/en/github-actions).

16 

17## Compare scheduling options

18 

19Claude Code offers three ways to schedule recurring or one-off work:

20 

21| | [Cloud](/en/routines) | [Desktop](/en/desktop-scheduled-tasks) | [`/loop`](/en/scheduled-tasks) |

22| :------------------------- | :----------------------------- | :------------------------------------- | :---------------------------------- |

23| Runs on | Anthropic cloud | Your machine | Your machine |

24| Requires machine on | No | Yes | Yes |

25| Requires open session | No | No | Yes |

26| Persistent across restarts | Yes | Yes | Restored on `--resume` if unexpired |

27| Access to local files | No (fresh clone) | Yes | Yes |

28| MCP servers | Connectors configured per task | [Config files](/en/mcp) and connectors | Inherits from session |

29| Permission prompts | No (runs autonomously) | Configurable per task | Inherits from session |

30| Customizable schedule | Via `/schedule` in the CLI | Yes | Yes |

31| Minimum interval | 1 hour | 1 minute | 1 minute |

32 

33<Tip>

34 Use **cloud tasks** for work that should run reliably without your machine. Use **Desktop tasks** when you need access to local files and tools. Use **`/loop`** for quick polling during a session.

35</Tip>

36 

37## Run a prompt repeatedly with /loop

38 

39The `/loop` [bundled skill](/en/commands) is the quickest way to run a prompt on repeat while the session stays open. Both the interval and the prompt are optional, and what you provide determines how the loop behaves.

40 

41| What you provide | Example | What happens |

42| :------------------------ | :-------------------------- | :------------------------------------------------------------------------------------------------------------ |

43| Interval and prompt | `/loop 5m check the deploy` | Your prompt runs on a [fixed schedule](#run-on-a-fixed-interval) |

44| Prompt only | `/loop check the deploy` | Your prompt runs at an [interval Claude chooses](#let-claude-choose-the-interval) each iteration |

45| Interval only, or nothing | `/loop` | The [built-in maintenance prompt](#run-the-built-in-maintenance-prompt) runs, or your `loop.md` if one exists |

46 

47You can also pass another command as the prompt, for example `/loop 20m /review-pr 1234`, to re-run a packaged workflow each iteration.

48 

49### Run on a fixed interval

50 

51When you supply an interval, Claude converts it to a cron expression, schedules the job, and confirms the cadence and job ID.

52 

53```text theme={null}

54/loop 5m check if the deployment finished and tell me what happened

55```

56 

57The interval can lead the prompt as a bare token like `30m`, or trail it as a clause like `every 2 hours`. Supported units are `s` for seconds, `m` for minutes, `h` for hours, and `d` for days.

58 

59Seconds are rounded up to the nearest minute since cron has one-minute granularity. Intervals that don't map to a clean cron step, such as `7m` or `90m`, are rounded to the nearest interval that does and Claude tells you what it picked.

60 

61### Let Claude choose the interval

62 

63When you omit the interval, Claude chooses one dynamically instead of running on a fixed cron schedule. After each iteration it picks a delay between one minute and one hour based on what it observed: short waits while a build is finishing or a PR is active, longer waits when nothing is pending. The chosen delay and the reason for it are printed at the end of each iteration.

64 

65The example below checks CI and review comments, with Claude waiting longer between iterations once the PR goes quiet:

66 

67```text theme={null}

68/loop check whether CI passed and address any review comments

69```

70 

71When you ask for a dynamic `/loop` schedule, Claude may use the [Monitor tool](/en/tools-reference#monitor-tool) directly. Monitor runs a background script and streams each output line back, which avoids polling altogether and is often more token-efficient and responsive than re-running a prompt on an interval.

72 

73A dynamically scheduled loop appears in your [scheduled task list](#manage-scheduled-tasks) like any other task, so you can list or cancel it the same way. The [jitter rules](#jitter) don't apply to it, but the [seven-day expiry](#seven-day-expiry) does: the loop ends automatically seven days after you start it.

74 

75<Note>

76 On Bedrock, Vertex AI, and Microsoft Foundry, a prompt with no interval runs on a fixed 10-minute schedule instead.

77</Note>

78 

79### Run the built-in maintenance prompt

80 

81When you omit the prompt, Claude uses a built-in maintenance prompt instead of one you supply. On each iteration it works through the following, in order:

82 

83* continue any unfinished work from the conversation

84* tend to the current branch's pull request: review comments, failed CI runs, merge conflicts

85* run cleanup passes such as bug hunts or simplification when nothing else is pending

86 

87Claude does not start new initiatives outside that scope, and irreversible actions such as pushing or deleting only proceed when they continue something the transcript already authorized.

88 

89```text theme={null}

90/loop

91```

92 

93A bare `/loop` runs this prompt at a [dynamically chosen interval](#let-claude-choose-the-interval). Add an interval, for example `/loop 15m`, to run it on a fixed schedule instead. To replace the built-in prompt with your own default, see [Customize the default prompt with loop.md](#customize-the-default-prompt-with-loop-md).

94 

95<Note>

96 On Bedrock, Vertex AI, and Microsoft Foundry, `/loop` with no prompt prints the usage message instead of starting the maintenance loop.

97</Note>

98 

99### Customize the default prompt with loop.md

100 

101A `loop.md` file replaces the built-in maintenance prompt with your own instructions. It defines a single default prompt for bare `/loop`, not a list of separate scheduled tasks, and is ignored whenever you supply a prompt on the command line. To schedule additional prompts alongside it, use `/loop <prompt>` or [ask Claude directly](#manage-scheduled-tasks).

102 

103Claude looks for the file in two locations and uses the first one it finds.

104 

105| Path | Scope |

106| :------------------ | :--------------------------------------------------------------- |

107| `.claude/loop.md` | Project-level. Takes precedence when both files exist. |

108| `~/.claude/loop.md` | User-level. Applies in any project that does not define its own. |

109 

110The file is plain Markdown with no required structure. Write it as if you were typing the `/loop` prompt directly. The following example keeps a release branch healthy:

111 

112```markdown title=".claude/loop.md" theme={null}

113Check the `release/next` PR. If CI is red, pull the failing job log,

114diagnose, and push a minimal fix. If new review comments have arrived,

115address each one and resolve the thread. If everything is green and

116quiet, say so in one line.

117```

118 

119Edits to `loop.md` take effect on the next iteration, so you can refine the instructions while a loop is running. When no `loop.md` exists in either location, the loop falls back to the built-in maintenance prompt. Keep the file concise: content beyond 25,000 bytes is truncated.

120 

121### Stop a loop

122 

123To stop a `/loop` while it is waiting for the next iteration, press `Esc`. This clears the pending wakeup so the loop does not fire again. Tasks you scheduled by [asking Claude directly](#manage-scheduled-tasks) are not affected by `Esc` and stay in place until you delete them.

124 

125## Set a one-time reminder

126 

127For one-shot reminders, describe what you want in natural language instead of using `/loop`. Claude schedules a single-fire task that deletes itself after running.

128 

129```text theme={null}

130remind me at 3pm to push the release branch

131```

132 

133```text theme={null}

134in 45 minutes, check whether the integration tests passed

135```

136 

137Claude pins the fire time to a specific minute and hour using a cron expression and confirms when it will fire.

138 

139## Manage scheduled tasks

140 

141Ask Claude in natural language to list or cancel tasks, or reference the underlying tools directly.

142 

143```text theme={null}

144what scheduled tasks do I have?

145```

146 

147```text theme={null}

148cancel the deploy check job

149```

150 

151Under the hood, Claude uses these tools:

152 

153| Tool | Purpose |

154| :----------- | :-------------------------------------------------------------------------------------------------------------- |

155| `CronCreate` | Schedule a new task. Accepts a 5-field cron expression, the prompt to run, and whether it recurs or fires once. |

156| `CronList` | List all scheduled tasks with their IDs, schedules, and prompts. |

157| `CronDelete` | Cancel a task by ID. |

158 

159Each scheduled task has an 8-character ID you can pass to `CronDelete`. A session can hold up to 50 scheduled tasks at once.

160 

161## How scheduled tasks run

162 

163The scheduler checks every second for due tasks and enqueues them at low priority. A scheduled prompt fires between your turns, not while Claude is mid-response. If Claude is busy when a task comes due, the prompt waits until the current turn ends.

164 

165All times are interpreted in your local timezone. A cron expression like `0 9 * * *` means 9am wherever you're running Claude Code, not UTC.

166 

167### Jitter

168 

169To avoid every session hitting the API at the same wall-clock moment, the scheduler adds a small deterministic offset to fire times:

170 

171* Recurring tasks fire up to 10% of their period late, capped at 15 minutes. An hourly job might fire anywhere from `:00` to `:06`.

172* One-shot tasks scheduled for the top or bottom of the hour fire up to 90 seconds early.

173 

174The offset is derived from the task ID, so the same task always gets the same offset. If exact timing matters, pick a minute that is not `:00` or `:30`, for example `3 9 * * *` instead of `0 9 * * *`, and the one-shot jitter will not apply.

175 

176### Seven-day expiry

177 

178Recurring tasks automatically expire 7 days after creation. The task fires one final time, then deletes itself. This bounds how long a forgotten loop can run. If you need a recurring task to last longer, cancel and recreate it before it expires, or use [Routines](/en/routines) or [Desktop scheduled tasks](/en/desktop-scheduled-tasks) for durable scheduling.

179 

180## Cron expression reference

181 

182`CronCreate` accepts standard 5-field cron expressions: `minute hour day-of-month month day-of-week`. All fields support wildcards (`*`), single values (`5`), steps (`*/15`), ranges (`1-5`), and comma-separated lists (`1,15,30`).

183 

184| Example | Meaning |

185| :------------- | :--------------------------- |

186| `*/5 * * * *` | Every 5 minutes |

187| `0 * * * *` | Every hour on the hour |

188| `7 * * * *` | Every hour at 7 minutes past |

189| `0 9 * * *` | Every day at 9am local |

190| `0 9 * * 1-5` | Weekdays at 9am local |

191| `30 14 15 3 *` | March 15 at 2:30pm local |

192 

193Day-of-week uses `0` or `7` for Sunday through `6` for Saturday. Extended syntax like `L`, `W`, `?`, and name aliases such as `MON` or `JAN` is not supported.

194 

195When both day-of-month and day-of-week are constrained, a date matches if either field matches. This follows standard vixie-cron semantics.

196 

197## Disable scheduled tasks

198 

199Set `CLAUDE_CODE_DISABLE_CRON=1` in your environment to disable the scheduler entirely. The cron tools and `/loop` become unavailable, and any already-scheduled tasks stop firing. See [Environment variables](/en/env-vars) for the full list of disable flags.

200 

201## Limitations

202 

203Session-scoped scheduling has inherent constraints:

204 

205* Tasks only fire while Claude Code is running and idle. Closing the terminal or letting the session exit stops them firing.

206* No catch-up for missed fires. If a task's scheduled time passes while Claude is busy on a long-running request, it fires once when Claude becomes idle, not once per missed interval.

207* Starting a fresh conversation clears all session-scoped tasks. Resuming with `claude --resume` or `claude --continue` restores tasks that have not expired: recurring tasks within seven days of creation, and one-shot tasks whose scheduled time has not yet passed. Background Bash and monitor tasks are never restored on resume.

208 

209For cron-driven automation that needs to run unattended:

210 

211* [Routines](/en/routines): run on Anthropic-managed infrastructure on a schedule, via API call, or on GitHub events

212* [GitHub Actions](/en/github-actions): use a `schedule` trigger in CI

213* [Desktop scheduled tasks](/en/desktop-scheduled-tasks): run locally on your machine

security.md +10 −7

Details

18 18 

19We designed Claude Code to be transparent and secure. For example, we require approval for bash commands before executing them, giving you direct control. This approach enables users and organizations to configure permissions directly.19We designed Claude Code to be transparent and secure. For example, we require approval for bash commands before executing them, giving you direct control. This approach enables users and organizations to configure permissions directly.

20 20 

21For detailed permission configuration, see [Identity and Access Management](/en/iam).21For detailed permission configuration, see [Permissions](/en/permissions).

22 22 

23### Built-in protections23### Built-in protections

24 24 


42* **Permission system**: Sensitive operations require explicit approval42* **Permission system**: Sensitive operations require explicit approval

43* **Context-aware analysis**: Detects potentially harmful instructions by analyzing the full request43* **Context-aware analysis**: Detects potentially harmful instructions by analyzing the full request

44* **Input sanitization**: Prevents command injection by processing user inputs44* **Input sanitization**: Prevents command injection by processing user inputs

45* **Command blocklist**: Blocks risky commands that fetch arbitrary content from the web like `curl` and `wget` by default. When explicitly allowed, be aware of [permission pattern limitations](/en/iam#tool-specific-permission-rules)45* **Command blocklist**: Blocks risky commands that fetch arbitrary content from the web like `curl` and `wget` by default. When explicitly allowed, be aware of [permission pattern limitations](/en/permissions#tool-specific-permission-rules)

46 46 

47### Privacy safeguards47### Privacy safeguards

48 48 


63* **Command injection detection**: Suspicious bash commands require manual approval even if previously allowlisted63* **Command injection detection**: Suspicious bash commands require manual approval even if previously allowlisted

64* **Fail-closed matching**: Unmatched commands default to requiring manual approval64* **Fail-closed matching**: Unmatched commands default to requiring manual approval

65* **Natural language descriptions**: Complex bash commands include explanations for user understanding65* **Natural language descriptions**: Complex bash commands include explanations for user understanding

66* **Secure credential storage**: API keys and tokens are encrypted. See [Credential Management](/en/iam#credential-management)66* **Secure credential storage**: API keys and tokens are encrypted. See [Credential Management](/en/authentication#credential-management)

67 67 

68<Warning>68<Warning>

69 **Windows WebDAV security risk**: When running Claude Code on Windows, we recommend against enabling WebDAV or allowing Claude Code to access paths such as `\\*` that may contain WebDAV subdirectories. [WebDAV has been deprecated by Microsoft](https://learn.microsoft.com/en-us/windows/whats-new/deprecated-features#:~:text=The%20Webclient%20\(WebDAV\)%20service%20is%20deprecated) due to security risks. Enabling WebDAV may allow Claude Code to trigger network requests to remote hosts, bypassing the permission system.69 **Windows WebDAV security risk**: When running Claude Code on Windows, we recommend against enabling WebDAV or allowing Claude Code to access paths such as `\\*` that may contain WebDAV subdirectories. [WebDAV has been deprecated by Microsoft](https://learn.microsoft.com/en-us/windows/whats-new/deprecated-features#:~:text=The%20Webclient%20\(WebDAV\)%20service%20is%20deprecated) due to security risks. Enabling WebDAV may allow Claude Code to trigger network requests to remote hosts, bypassing the permission system.


752. Avoid piping untrusted content directly to Claude752. Avoid piping untrusted content directly to Claude

763. Verify proposed changes to critical files763. Verify proposed changes to critical files

774. Use virtual machines (VMs) to run scripts and make tool calls, especially when interacting with external web services774. Use virtual machines (VMs) to run scripts and make tool calls, especially when interacting with external web services

785. Report suspicious behavior with `/bug`785. Report suspicious behavior with `/feedback`

79 79 

80<Warning>80<Warning>

81 While these protections significantly reduce risk, no system is completely81 While these protections significantly reduce risk, no system is completely


106 106 

107For more details on cloud execution, see [Claude Code on the web](/en/claude-code-on-the-web).107For more details on cloud execution, see [Claude Code on the web](/en/claude-code-on-the-web).

108 108 

109[Remote Control](/en/remote-control) sessions work differently: the web interface connects to a Claude Code process running on your local machine. All code execution and file access stays local, and the same data that flows during any local Claude Code session travels through the Anthropic API over TLS. No cloud VMs or sandboxing are involved. The connection uses multiple short-lived, narrowly scoped credentials, each limited to a specific purpose and expiring independently, to limit the blast radius of any single compromised credential.

110 

109## Security best practices111## Security best practices

110 112 

111### Working with sensitive code113### Working with sensitive code

112 114 

113* Review all suggested changes before approval115* Review all suggested changes before approval

114* Use project-specific permission settings for sensitive repositories116* Use project-specific permission settings for sensitive repositories

115* Consider using [devcontainers](/en/devcontainer) for additional isolation117* Consider using [dev containers](/en/devcontainer) for additional isolation

116* Regularly audit your permission settings with `/permissions`118* Regularly audit your permission settings with `/permissions`

117 119 

118### Team security120### Team security

119 121 

120* Use [managed settings](/en/iam#managed-settings) to enforce organizational standards122* Use [managed settings](/en/settings#settings-files) to enforce organizational standards

121* Share approved permission configurations through version control123* Share approved permission configurations through version control

122* Train team members on security best practices124* Train team members on security best practices

123* Monitor Claude Code usage through [OpenTelemetry metrics](/en/monitoring-usage)125* Monitor Claude Code usage through [OpenTelemetry metrics](/en/monitoring-usage)

126* Audit or block settings changes during sessions with [`ConfigChange` hooks](/en/hooks#configchange)

124 127 

125### Reporting security issues128### Reporting security issues

126 129 


134## Related resources137## Related resources

135 138 

136* [Sandboxing](/en/sandboxing) - Filesystem and network isolation for bash commands139* [Sandboxing](/en/sandboxing) - Filesystem and network isolation for bash commands

137* [Identity and Access Management](/en/iam) - Configure permissions and access controls140* [Permissions](/en/permissions) - Configure permissions and access controls

138* [Monitoring usage](/en/monitoring-usage) - Track and audit Claude Code activity141* [Monitoring usage](/en/monitoring-usage) - Track and audit Claude Code activity

139* [Development containers](/en/devcontainer) - Secure, isolated environments142* [Development containers](/en/devcontainer) - Secure, isolated environments

140* [Anthropic Trust Center](https://trust.anthropic.com) - Security certifications and compliance143* [Anthropic Trust Center](https://trust.anthropic.com) - Security certifications and compliance

server-managed-settings.md +224 −0 added

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# Configure server-managed settings

6 

7> Centrally configure Claude Code for your organization through server-delivered settings, without requiring device management infrastructure.

8 

9Server-managed settings allow administrators to centrally configure Claude Code through a web-based interface on Claude.ai. Claude Code clients automatically receive these settings when users authenticate with their organization credentials.

10 

11This approach is designed for organizations that do not have device management infrastructure in place, or need to manage settings for users on unmanaged devices.

12 

13<Note>

14 Server-managed settings are available for [Claude for Teams](https://claude.com/pricing?utm_source=claude_code\&utm_medium=docs\&utm_content=server_settings_teams#team-&-enterprise) and [Claude for Enterprise](https://anthropic.com/contact-sales?utm_source=claude_code\&utm_medium=docs\&utm_content=server_settings_enterprise) customers.

15</Note>

16 

17## Requirements

18 

19To use server-managed settings, you need:

20 

21* Claude for Teams or Claude for Enterprise plan

22* Claude Code version 2.1.38 or later for Claude for Teams, or version 2.1.30 or later for Claude for Enterprise

23* Network access to `api.anthropic.com`

24 

25## Choose between server-managed and endpoint-managed settings

26 

27Claude Code supports two approaches for centralized configuration. Server-managed settings deliver configuration from Anthropic's servers. [Endpoint-managed settings](/en/settings#settings-files) are deployed directly to devices through native OS policies (macOS managed preferences, Windows registry) or managed settings files.

28 

29| Approach | Best for | Security model |

30| :----------------------------------------------------------- | :------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------- |

31| **Server-managed settings** | Organizations without MDM, or users on unmanaged devices | Settings delivered from Anthropic's servers at authentication time |

32| **[Endpoint-managed settings](/en/settings#settings-files)** | Organizations with MDM or endpoint management | Settings deployed to devices via MDM configuration profiles, registry policies, or managed settings files |

33 

34If your devices are enrolled in an MDM or endpoint management solution, endpoint-managed settings provide stronger security guarantees because the settings file can be protected from user modification at the OS level.

35 

36## Configure server-managed settings

37 

38<Steps>

39 <Step title="Open the admin console">

40 In [Claude.ai](https://claude.ai), navigate to **Admin Settings > Claude Code > Managed settings**.

41 </Step>

42 

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 [hooks](/en/hooks), [environment variables](/en/env-vars), and [managed-only settings](/en/permissions#managed-only-settings) like `allowManagedPermissionRulesOnly`.

45 

46 This example enforces a permission deny list, prevents users from bypassing permissions, and restricts permission rules to those defined in managed settings:

47 

48 ```json theme={null}

49 {

50 "permissions": {

51 "deny": [

52 "Bash(curl *)",

53 "Read(./.env)",

54 "Read(./.env.*)",

55 "Read(./secrets/**)"

56 ],

57 "disableBypassPermissionsMode": "disable"

58 },

59 "allowManagedPermissionRulesOnly": true

60 }

61 ```

62 

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

64 

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

66 

67 ```json theme={null}

68 {

69 "hooks": {

70 "PostToolUse": [

71 {

72 "matcher": "Edit|Write",

73 "hooks": [

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

75 ]

76 }

77 ]

78 }

79 }

80 ```

81 

82 To configure the [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) classifier so it knows which repos, buckets, and domains your organization trusts:

83 

84 ```json theme={null}

85 {

86 "autoMode": {

87 "environment": [

88 "Source control: github.example.com/acme-corp and all repos under it",

89 "Trusted cloud buckets: s3://acme-build-artifacts, gs://acme-ml-datasets",

90 "Trusted internal domains: *.corp.example.com"

91 ]

92 }

93 }

94 ```

95 

96 Because hooks execute shell commands, users see a [security approval dialog](#security-approval-dialogs) before they're applied. See [Configure auto mode](/en/auto-mode-config) for how the `autoMode` entries affect what the classifier blocks and important warnings about the `allow` and `soft_deny` fields.

97 </Step>

98 

99 <Step title="Save and deploy">

100 Save your changes. Claude Code clients receive the updated settings on their next startup or hourly polling cycle.

101 </Step>

102</Steps>

103 

104### Verify settings delivery

105 

106To confirm that settings are being applied, ask a user to restart Claude Code. If the configuration includes settings that trigger the [security approval dialog](#security-approval-dialogs), the user sees a prompt describing the managed settings on startup. You can also verify that managed permission rules are active by having a user run `/permissions` to view their effective permission rules.

107 

108### Access control

109 

110The following roles can manage server-managed settings:

111 

112* **Primary Owner**

113* **Owner**

114 

115Restrict access to trusted personnel, as settings changes apply to all users in the organization.

116 

117### Managed-only settings

118 

119Most [settings keys](/en/settings#available-settings) work in any scope. A handful of keys are only read from managed settings and have no effect when placed in user or project settings files. See [managed-only settings](/en/permissions#managed-only-settings) for the full list. Any setting not on that list can still be placed in managed settings and takes the highest precedence.

120 

121### Current limitations

122 

123Server-managed settings have the following limitations:

124 

125* Settings apply uniformly to all users in the organization. Per-group configurations are not yet supported.

126* [MCP server configurations](/en/mcp#managed-mcp-configuration) cannot be distributed through server-managed settings.

127 

128## Settings delivery

129 

130### Settings precedence

131 

132Server-managed settings and [endpoint-managed settings](/en/settings#settings-files) both occupy the highest tier in the Claude Code [settings hierarchy](/en/settings#settings-precedence). No other settings level can override them, including command line arguments.

133 

134Within the managed tier, the first source that delivers a non-empty configuration wins. Server-managed settings are checked first, then endpoint-managed settings. Sources do not merge: if server-managed settings deliver any keys at all, endpoint-managed settings are ignored entirely. If server-managed settings deliver nothing, endpoint-managed settings apply.

135 

136If you clear your server-managed configuration in the admin console with the intent of falling back to an endpoint-managed plist or registry policy, be aware that [cached settings](#fetch-and-caching-behavior) persist on client machines until the next successful fetch. Run `/status` to see which managed source is active.

137 

138### Fetch and caching behavior

139 

140Claude Code fetches settings from Anthropic's servers at startup and polls for updates hourly during active sessions.

141 

142**First launch without cached settings:**

143 

144* Claude Code fetches settings asynchronously

145* If the fetch fails, Claude Code continues without managed settings

146* There is a brief window before settings load where restrictions are not yet enforced

147 

148**Subsequent launches with cached settings:**

149 

150* Cached settings apply immediately at startup

151* Claude Code fetches fresh settings in the background

152* Cached settings persist through network failures

153 

154Claude Code applies settings updates automatically without a restart, except for advanced settings like OpenTelemetry configuration, which require a full restart to take effect.

155 

156### Enforce fail-closed startup

157 

158By default, if the remote settings fetch fails at startup, the CLI continues without managed settings. For environments where this brief unenforced window is unacceptable, set `forceRemoteSettingsRefresh: true` in your managed settings.

159 

160When this setting is active, the CLI blocks at startup until remote settings are freshly fetched. If the fetch fails, the CLI exits rather than proceeding without the policy. This setting self-perpetuates: once delivered from the server, it is also cached locally so that subsequent startups enforce the same behavior even before the first successful fetch of a new session.

161 

162To enable this, add the key to your managed settings configuration:

163 

164```json theme={null}

165{

166 "forceRemoteSettingsRefresh": true

167}

168```

169 

170Before enabling this setting, ensure your network policies allow connectivity to `api.anthropic.com`. If that endpoint is unreachable, the CLI exits at startup and users cannot start Claude Code.

171 

172### Security approval dialogs

173 

174Certain settings that could pose security risks require explicit user approval before being applied:

175 

176* **Shell command settings**: settings that execute shell commands

177* **Custom environment variables**: variables not in the known safe allowlist

178* **Hook configurations**: any hook definition

179 

180When these settings are present, users see a security dialog explaining what is being configured. Users must approve to proceed. If a user rejects the settings, Claude Code exits.

181 

182<Note>

183 In non-interactive mode with the `-p` flag, Claude Code skips security dialogs and applies settings without user approval.

184</Note>

185 

186## Platform availability

187 

188Server-managed settings require a direct connection to `api.anthropic.com` and are not available when using third-party model providers:

189 

190* Amazon Bedrock

191* Google Vertex AI

192* Microsoft Foundry

193* Custom API endpoints via `ANTHROPIC_BASE_URL` or [LLM gateways](/en/llm-gateway)

194 

195## Audit logging

196 

197Audit log events for settings changes are available through the compliance API or audit log export. Contact your Anthropic account team for access.

198 

199Audit events include the type of action performed, the account and device that performed the action, and references to the previous and new values.

200 

201## Security considerations

202 

203Server-managed settings provide centralized policy enforcement, but they operate as a client-side control. On unmanaged devices, users with admin or sudo access can modify the Claude Code binary, filesystem, or network configuration.

204 

205| Scenario | Behavior |

206| :----------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

207| User edits the cached settings file | Tampered file applies at startup, but correct settings restore on the next server fetch |

208| User deletes the cached settings file | First-launch behavior occurs: settings fetch asynchronously with a brief unenforced window |

209| API is unavailable | Cached settings apply if available, otherwise managed settings are not enforced until the next successful fetch. With `forceRemoteSettingsRefresh: true`, the CLI exits instead of continuing |

210| User authenticates with a different organization | Settings are not delivered for accounts outside the managed organization |

211| User sets a non-default `ANTHROPIC_BASE_URL` | Server-managed settings are bypassed when using third-party API providers |

212 

213To detect runtime configuration changes, use [`ConfigChange` hooks](/en/hooks#configchange) to log modifications or block unauthorized changes before they take effect.

214 

215For stronger enforcement guarantees, use [endpoint-managed settings](/en/settings#settings-files) on devices enrolled in an MDM solution.

216 

217## See also

218 

219Related pages for managing Claude Code configuration:

220 

221* [Settings](/en/settings): complete configuration reference including all available settings

222* [Endpoint-managed settings](/en/settings#settings-files): managed settings deployed to devices by IT

223* [Authentication](/en/authentication): set up user access to Claude Code

224* [Security](/en/security): security safeguards and best practices

settings.md +259 −315

Details

15### Available scopes15### Available scopes

16 16 

17| Scope | Location | Who it affects | Shared with team? |17| Scope | Location | Who it affects | Shared with team? |

18| :---------- | :----------------------------------- | :----------------------------------- | :--------------------- |18| :---------- | :--------------------------------------------------------------------------------- | :----------------------------------- | :--------------------- |

19| **Managed** | System-level `managed-settings.json` | All users on the machine | Yes (deployed by IT) |19| **Managed** | Server-managed settings, plist / registry, or system-level `managed-settings.json` | All users on the machine | Yes (deployed by IT) |

20| **User** | `~/.claude/` directory | You, across all projects | No |20| **User** | `~/.claude/` directory | You, across all projects | No |

21| **Project** | `.claude/` in repository | All collaborators on this repository | Yes (committed to git) |21| **Project** | `.claude/` in repository | All collaborators on this repository | Yes (committed to git) |

22| **Local** | `.claude/*.local.*` files | You, in this repository only | No (gitignored) |22| **Local** | `.claude/settings.local.json` | You, in this repository only | No (gitignored) |

23 23 

24### When to use each scope24### When to use each scope

25 25 


66| Feature | User location | Project location | Local location |66| Feature | User location | Project location | Local location |

67| :-------------- | :------------------------ | :--------------------------------- | :----------------------------- |67| :-------------- | :------------------------ | :--------------------------------- | :----------------------------- |

68| **Settings** | `~/.claude/settings.json` | `.claude/settings.json` | `.claude/settings.local.json` |68| **Settings** | `~/.claude/settings.json` | `.claude/settings.json` | `.claude/settings.local.json` |

69| **Subagents** | `~/.claude/agents/` | `.claude/agents/` | |69| **Subagents** | `~/.claude/agents/` | `.claude/agents/` | None |

70| **MCP servers** | `~/.claude.json` | `.mcp.json` | `~/.claude.json` (per-project) |70| **MCP servers** | `~/.claude.json` | `.mcp.json` | `~/.claude.json` (per-project) |

71| **Plugins** | `~/.claude/settings.json` | `.claude/settings.json` | `.claude/settings.local.json` |71| **Plugins** | `~/.claude/settings.json` | `.claude/settings.json` | `.claude/settings.local.json` |

72| **CLAUDE.md** | `~/.claude/CLAUDE.md` | `CLAUDE.md` or `.claude/CLAUDE.md` | `CLAUDE.local.md` |72| **CLAUDE.md** | `~/.claude/CLAUDE.md` | `CLAUDE.md` or `.claude/CLAUDE.md` | `CLAUDE.local.md` |


75 75 

76## Settings files76## Settings files

77 77 

78The `settings.json` file is our official mechanism for configuring Claude78The `settings.json` file is the official mechanism for configuring Claude

79Code through hierarchical settings:79Code through hierarchical settings:

80 80 

81* **User settings** are defined in `~/.claude/settings.json` and apply to all81* **User settings** are defined in `~/.claude/settings.json` and apply to all


83* **Project settings** are saved in your project directory:83* **Project settings** are saved in your project directory:

84 * `.claude/settings.json` for settings that are checked into source control and shared with your team84 * `.claude/settings.json` for settings that are checked into source control and shared with your team

85 * `.claude/settings.local.json` for settings that are not checked in, useful for personal preferences and experimentation. Claude Code will configure git to ignore `.claude/settings.local.json` when it is created.85 * `.claude/settings.local.json` for settings that are not checked in, useful for personal preferences and experimentation. Claude Code will configure git to ignore `.claude/settings.local.json` when it is created.

86* **Managed settings**: For organizations that need centralized control, Claude Code supports `managed-settings.json` and `managed-mcp.json` files that can be deployed to system directories:86* **Managed settings**: For organizations that need centralized control, Claude Code supports multiple delivery mechanisms for managed settings. All use the same JSON format and cannot be overridden by user or project settings:

87 

88 * **Server-managed settings**: delivered from Anthropic's servers via the Claude.ai admin console. See [server-managed settings](/en/server-managed-settings).

89 * **MDM/OS-level policies**: delivered through native device management on macOS and Windows:

90 * macOS: `com.anthropic.claudecode` managed preferences domain. The plist's top-level keys mirror `managed-settings.json`, with nested settings as dictionaries and arrays as plist arrays. Deploy via configuration profiles in Jamf, Iru (Kandji), or similar MDM tools.

91 * Windows: `HKLM\SOFTWARE\Policies\ClaudeCode` registry key with a `Settings` value (REG\_SZ or REG\_EXPAND\_SZ) containing JSON (deployed via Group Policy or Intune)

92 * Windows (user-level): `HKCU\SOFTWARE\Policies\ClaudeCode` (lowest policy priority, only used when no admin-level source exists)

93 * **File-based**: `managed-settings.json` and `managed-mcp.json` deployed to system directories:

87 94 

88 * macOS: `/Library/Application Support/ClaudeCode/`95 * macOS: `/Library/Application Support/ClaudeCode/`

89 * Linux and WSL: `/etc/claude-code/`96 * Linux and WSL: `/etc/claude-code/`

90 * Windows: `C:\Program Files\ClaudeCode\`97 * Windows: `C:\Program Files\ClaudeCode\`

91 98 

92 <Note>99 <Warning>

93 These are system-wide paths (not user home directories like `~/Library/...`) that require administrator privileges. They are designed to be deployed by IT administrators.100 The legacy Windows path `C:\ProgramData\ClaudeCode\managed-settings.json` is no longer supported as of v2.1.75. Administrators who deployed settings to that location must migrate files to `C:\Program Files\ClaudeCode\managed-settings.json`.

94 </Note>101 </Warning>

102 

103 File-based managed settings also support a drop-in directory at `managed-settings.d/` in the same system directory alongside `managed-settings.json`. This lets separate teams deploy independent policy fragments without coordinating edits to a single file.

104 

105 Following the systemd convention, `managed-settings.json` is merged first as the base, then all `*.json` files in the drop-in directory are sorted alphabetically and merged on top. Later files override earlier ones for scalar values; arrays are concatenated and de-duplicated; objects are deep-merged. Hidden files starting with `.` are ignored.

106 

107 Use numeric prefixes to control merge order, for example `10-telemetry.json` and `20-security.json`.

95 108 

96 See [Managed settings](/en/iam#managed-settings) and [Managed MCP configuration](/en/mcp#managed-mcp-configuration) for details.109 See [managed settings](/en/permissions#managed-only-settings) and [Managed MCP configuration](/en/mcp#managed-mcp-configuration) for details.

110 

111 This [repository](https://github.com/anthropics/claude-code/tree/main/examples/mdm) includes starter deployment templates for Jamf, Iru (Kandji), Intune, and Group Policy. Use these as starting points and adjust them to fit your needs.

97 112 

98 <Note>113 <Note>

99 Managed deployments can also restrict **plugin marketplace additions** using114 Managed deployments can also restrict **plugin marketplace additions** using

100 `strictKnownMarketplaces`. For more information, see [Managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions).115 `strictKnownMarketplaces`. For more information, see [Managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions).

101 </Note>116 </Note>

102* **Other configuration** is stored in `~/.claude.json`. This file contains your preferences (theme, notification settings, editor mode), OAuth session, [MCP server](/en/mcp) configurations for user and local scopes, per-project state (allowed tools, trust settings), and various caches. Project-scoped MCP servers are stored separately in `.mcp.json`.117* **Other configuration** is stored in `~/.claude.json`. This file contains your OAuth session, [MCP server](/en/mcp) configurations for user and local scopes, per-project state (allowed tools, trust settings), and various caches. Project-scoped MCP servers are stored separately in `.mcp.json`.

103 118 

104<Note>119<Note>

105 Claude Code automatically creates timestamped backups of configuration files and retains the five most recent backups to prevent data loss.120 Claude Code automatically creates timestamped backups of configuration files and retains the five most recent backups to prevent data loss.


107 122 

108```JSON Example settings.json theme={null}123```JSON Example settings.json theme={null}

109{124{

125 "$schema": "https://json.schemastore.org/claude-code-settings.json",

110 "permissions": {126 "permissions": {

111 "allow": [127 "allow": [

112 "Bash(npm run lint)",128 "Bash(npm run lint)",


132}148}

133```149```

134 150 

151The `$schema` line in the example above points to the [official JSON schema](https://json.schemastore.org/claude-code-settings.json) for Claude Code settings. Adding it to your `settings.json` enables autocomplete and inline validation in VS Code, Cursor, and any other editor that supports JSON schema validation.

152 

153The published schema is updated periodically and may not include settings added in the most recent CLI releases, so a validation warning on a recently documented field does not necessarily mean your configuration is invalid.

154 

135### Available settings155### Available settings

136 156 

137`settings.json` supports a number of options:157`settings.json` supports a number of options:

138 158 

139| Key | Description | Example |159| Key | Description | Example |

140| :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------- |160| :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- |

161| `agent` | Run the main thread as a named subagent. Applies that subagent's system prompt, tool restrictions, and model. See [Invoke subagents explicitly](/en/sub-agents#invoke-subagents-explicitly) | `"code-reviewer"` |

162| `allowedChannelPlugins` | (Managed settings only) Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Undefined = fall back to the default, empty array = block all channel plugins. Requires `channelsEnabled: true`. See [Restrict which channel plugins can run](/en/channels#restrict-which-channel-plugins-can-run) | `[{ "marketplace": "claude-plugins-official", "plugin": "telegram" }]` |

163| `allowedHttpHookUrls` | Allowlist of URL patterns that HTTP hooks may target. Supports `*` as a wildcard. When set, hooks with non-matching URLs are blocked. Undefined = no restriction, empty array = block all HTTP hooks. Arrays merge across settings sources. See [Hook configuration](#hook-configuration) | `["https://hooks.example.com/*"]` |

164| `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" }]` |

165| `allowManagedHooksOnly` | (Managed settings only) Only managed hooks, SDK hooks, and hooks from plugins force-enabled in managed settings `enabledPlugins` are loaded. User, project, and all other plugin hooks are blocked. See [Hook configuration](#hook-configuration) | `true` |

166| `allowManagedMcpServersOnly` | (Managed settings only) Only `allowedMcpServers` from managed settings are respected. `deniedMcpServers` still merges from all sources. Users can still add MCP servers, but only the admin-defined allowlist applies. See [Managed MCP configuration](/en/mcp#managed-mcp-configuration) | `true` |

167| `allowManagedPermissionRulesOnly` | (Managed settings only) Prevent user and project settings from defining `allow`, `ask`, or `deny` permission rules. Only rules in managed settings apply. See [Managed-only settings](/en/permissions#managed-only-settings) | `true` |

168| `alwaysThinkingEnabled` | Enable [extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) by default for all sessions. Typically configured via the `/config` command rather than editing directly | `true` |

141| `apiKeyHelper` | Custom script, to be executed in `/bin/sh`, to generate an auth value. This value will be sent as `X-Api-Key` and `Authorization: Bearer` headers for model requests | `/bin/generate_temp_api_key.sh` |169| `apiKeyHelper` | Custom script, to be executed in `/bin/sh`, to generate an auth value. This value will be sent as `X-Api-Key` and `Authorization: Bearer` headers for model requests | `/bin/generate_temp_api_key.sh` |

142| `cleanupPeriodDays` | Sessions inactive for longer than this period are deleted at startup. Setting to `0` immediately deletes all sessions. (default: 30 days) | `20` |170| `attribution` | Customize attribution for git commits and pull requests. See [Attribution settings](#attribution-settings) | `{"commit": "🤖 Generated with Claude Code", "pr": ""}` |

171| `autoMemoryDirectory` | Custom directory for [auto memory](/en/memory#storage-location) storage. Accepts `~/`-expanded paths. Not accepted in project settings (`.claude/settings.json`) to prevent shared repos from redirecting memory writes to sensitive locations. Accepted from policy, local, and user settings | `"~/my-memory-dir"` |

172| `autoMode` | Customize what the [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) classifier blocks and allows. Contains `environment`, `allow`, and `soft_deny` arrays of prose rules. Include the literal string `"$defaults"` in an array to inherit the built-in rules at that position. See [Configure auto mode](/en/auto-mode-config). Not read from shared project settings | `{"soft_deny": ["$defaults", "Never run terraform apply"]}` |

173| `autoScrollEnabled` | In [fullscreen rendering](/en/fullscreen), follow new output to the bottom of the conversation. Default: `true`. Appears in `/config` as **Auto-scroll**. Permission prompts still scroll into view when this is off | `false` |

174| `autoUpdatesChannel` | Release channel to follow for updates. Use `"stable"` for a version that is typically about one week old and skips versions with major regressions, or `"latest"` (default) for the most recent release | `"stable"` |

175| `availableModels` | Restrict which models users can select via `/model`, `--model`, or `ANTHROPIC_MODEL`. Does not affect the Default option. See [Restrict model selection](/en/model-config#restrict-model-selection) | `["sonnet", "haiku"]` |

176| `awaySummaryEnabled` | Show a one-line session recap when you return to the terminal after a few minutes away. Set to `false` or turn off Session recap in `/config` to disable. Same as [`CLAUDE_CODE_ENABLE_AWAY_SUMMARY`](/en/env-vars) | `true` |

177| `awsAuthRefresh` | Custom script that modifies the `.aws` directory (see [advanced credential configuration](/en/amazon-bedrock#advanced-credential-configuration)) | `aws sso login --profile myprofile` |

178| `awsCredentialExport` | Custom script that outputs JSON with AWS credentials (see [advanced credential configuration](/en/amazon-bedrock#advanced-credential-configuration)) | `/bin/generate_aws_grant.sh` |

179| `blockedMarketplaces` | (Managed settings only) Blocklist of marketplace sources. Enforced on marketplace add and on plugin install, update, refresh, and auto-update, so a marketplace added before the policy was set cannot be used to fetch plugins. Blocked sources are checked before downloading, so they never touch the filesystem. See [Managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) | `[{ "source": "github", "repo": "untrusted/plugins" }]` |

180| `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` |

181| `cleanupPeriodDays` | Session files older than this period are deleted at startup (default: 30 days, minimum 1). Setting to `0` is rejected with a validation error. Also controls the age cutoff for automatic removal of [orphaned subagent worktrees](/en/common-workflows#worktree-cleanup) at startup. To disable transcript writes entirely, set the [`CLAUDE_CODE_SKIP_PROMPT_HISTORY`](/en/env-vars) environment variable, or in non-interactive mode (`-p`) use the `--no-session-persistence` flag or the `persistSession: false` SDK option. | `20` |

143| `companyAnnouncements` | Announcement to display to users at startup. If multiple announcements are provided, they will be cycled through at random. | `["Welcome to Acme Corp! Review our code guidelines at docs.acme.com"]` |182| `companyAnnouncements` | Announcement to display to users at startup. If multiple announcements are provided, they will be cycled through at random. | `["Welcome to Acme Corp! Review our code guidelines at docs.acme.com"]` |

183| `defaultShell` | Default shell for input-box `!` commands. Accepts `"bash"` (default) or `"powershell"`. Setting `"powershell"` routes interactive `!` commands through PowerShell on Windows. Requires `CLAUDE_CODE_USE_POWERSHELL_TOOL=1`. See [PowerShell tool](/en/tools-reference#powershell-tool) | `"powershell"` |

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" }]` |

185| `disableAllHooks` | Disable all [hooks](/en/hooks) and any custom [status line](/en/statusline) | `true` |

186| `disableAutoMode` | Set to `"disable"` to prevent [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) from being activated. Removes `auto` from the `Shift+Tab` cycle and rejects `--permission-mode auto` at startup. Most useful in [managed settings](/en/permissions#managed-settings) where users cannot override it | `"disable"` |

187| `disableDeepLinkRegistration` | Set to `"disable"` to prevent Claude Code from registering the `claude-cli://` protocol handler with the operating system on startup. Deep links let external tools open a Claude Code session with a pre-filled prompt via `claude-cli://open?q=...`. The `q` parameter supports multi-line prompts using URL-encoded newlines (`%0A`). Useful in environments where protocol handler registration is restricted or managed separately | `"disable"` |

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

189| `disableSkillShellExecution` | Disable inline shell execution for `` !`...` `` and ` ```! ` blocks in [skills](/en/skills) and custom commands from user, project, plugin, or additional-directory sources. Commands are replaced with `[shell command execution disabled by policy]` instead of being run. Bundled and managed skills are not affected. Most useful in [managed settings](/en/permissions#managed-settings) where users cannot override it | `true` |

190| `editorMode` | Key binding mode for the input prompt: `"normal"` or `"vim"`. Default: `"normal"`. Appears in `/config` as **Editor mode** | `"vim"` |

191| `effortLevel` | Persist the [effort level](/en/model-config#adjust-effort-level) across sessions. Accepts `"low"`, `"medium"`, `"high"`, or `"xhigh"`. Written automatically when you run `/effort` with one of those values. See [Adjust effort level](/en/model-config#adjust-effort-level) for supported models | `"xhigh"` |

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

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

144| `env` | Environment variables that will be applied to every session | `{"FOO": "bar"}` |194| `env` | Environment variables that will be applied to every session | `{"FOO": "bar"}` |

145| `attribution` | Customize attribution for git commits and pull requests. See [Attribution settings](#attribution-settings) | `{"commit": "🤖 Generated with Claude Code", "pr": ""}` |195| `fastModePerSessionOptIn` | When `true`, fast mode does not persist across sessions. Each session starts with fast mode off, requiring users to enable it with `/fast`. The user's fast mode preference is still saved. See [Require per-session opt-in](/en/fast-mode#require-per-session-opt-in) | `true` |

146| `includeCoAuthoredBy` | **Deprecated**: Use `attribution` instead. Whether to include the `co-authored-by Claude` byline in git commits and pull requests (default: `true`) | `false` |196| `feedbackSurveyRate` | Probability (0–1) that the [session quality survey](/en/data-usage#session-quality-surveys) appears when eligible. Set to `0` to suppress entirely. Useful when using Bedrock, Vertex, or Foundry where the default sample rate does not apply | `0.05` |

147| `permissions` | See table below for structure of permissions. | |197| `fileSuggestion` | Configure a custom script for `@` file autocomplete. See [File suggestion settings](#file-suggestion-settings) | `{"type": "command", "command": "~/.claude/file-suggestion.sh"}` |

198| `forceLoginMethod` | Use `claudeai` to restrict login to Claude.ai accounts, `console` to restrict login to Claude Console (API usage billing) accounts | `claudeai` |

199| `forceLoginOrgUUID` | Require login to belong to a specific organization. Accepts a single UUID string, which also pre-selects that organization during login, or an array of UUIDs where any listed organization is accepted without pre-selection. When set in managed settings, login fails if the authenticated account does not belong to a listed organization; an empty array fails closed and blocks login with a misconfiguration message | `"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` or `["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"]` |

200| `forceRemoteSettingsRefresh` | (Managed settings only) Block CLI startup until remote managed settings are freshly fetched from the server. If the fetch fails, the CLI exits rather than continuing with cached or no settings. When not set, startup continues without waiting for remote settings. See [fail-closed enforcement](/en/server-managed-settings#enforce-fail-closed-startup) | `true` |

148| `hooks` | Configure custom commands to run at lifecycle events. See [hooks documentation](/en/hooks) for format | See [hooks](/en/hooks) |201| `hooks` | Configure custom commands to run at lifecycle events. See [hooks documentation](/en/hooks) for format | See [hooks](/en/hooks) |

149| `disableAllHooks` | Disable all [hooks](/en/hooks) | `true` |202| `httpHookAllowedEnvVars` | Allowlist of environment variable names HTTP hooks may interpolate into headers. When set, each hook's effective `allowedEnvVars` is the intersection with this list. Undefined = no restriction. Arrays merge across settings sources. See [Hook configuration](#hook-configuration) | `["MY_TOKEN", "HOOK_SECRET"]` |

150| `allowManagedHooksOnly` | (Managed settings only) Prevent loading of user, project, and plugin hooks. Only allows managed hooks and SDK hooks. See [Hook configuration](#hook-configuration) | `true` |203| `includeCoAuthoredBy` | **Deprecated**: Use `attribution` instead. Whether to include the `co-authored-by Claude` byline in git commits and pull requests (default: `true`) | `false` |

151| `model` | Override the default model to use for Claude Code | `"claude-sonnet-4-5-20250929"` |204| `includeGitInstructions` | Include built-in commit and PR workflow instructions and the git status snapshot in Claude's system prompt (default: `true`). Set to `false` to remove both, for example when using your own git workflow skills. The `CLAUDE_CODE_DISABLE_GIT_INSTRUCTIONS` environment variable takes precedence over this setting when set | `false` |

205| `language` | Configure Claude's preferred response language (e.g., `"japanese"`, `"spanish"`, `"french"`). Claude will respond in this language by default. Also sets the [voice dictation](/en/voice-dictation#change-the-dictation-language) language | `"japanese"` |

206| `minimumVersion` | Floor that prevents background auto-updates and `claude update` from installing a version below this one. Switching from the `"latest"` channel to `"stable"` via `/config` prompts you to stay on the current version or allow the downgrade. Choosing to stay sets this value. Also useful in [managed settings](/en/permissions#managed-settings) to pin an organization-wide minimum | `"2.1.100"` |

207| `model` | Override the default model to use for Claude Code | `"claude-sonnet-4-6"` |

208| `modelOverrides` | Map Anthropic model IDs to provider-specific model IDs such as Bedrock inference profile ARNs. Each model picker entry uses its mapped value when calling the provider API. See [Override model IDs per version](/en/model-config#override-model-ids-per-version) | `{"claude-opus-4-6": "arn:aws:bedrock:..."}` |

152| `otelHeadersHelper` | Script to generate dynamic OpenTelemetry headers. Runs at startup and periodically (see [Dynamic headers](/en/monitoring-usage#dynamic-headers)) | `/bin/generate_otel_headers.sh` |209| `otelHeadersHelper` | Script to generate dynamic OpenTelemetry headers. Runs at startup and periodically (see [Dynamic headers](/en/monitoring-usage#dynamic-headers)) | `/bin/generate_otel_headers.sh` |

153| `statusLine` | Configure a custom status line to display context. See [`statusLine` documentation](/en/statusline) | `{"type": "command", "command": "~/.claude/statusline.sh"}` |

154| `fileSuggestion` | Configure a custom script for `@` file autocomplete. See [File suggestion settings](#file-suggestion-settings) | `{"type": "command", "command": "~/.claude/file-suggestion.sh"}` |

155| `respectGitignore` | Control whether the `@` file picker respects `.gitignore` patterns. When `true` (default), files matching `.gitignore` patterns are excluded from suggestions | `false` |

156| `outputStyle` | Configure an output style to adjust the system prompt. See [output styles documentation](/en/output-styles) | `"Explanatory"` |210| `outputStyle` | Configure an output style to adjust the system prompt. See [output styles documentation](/en/output-styles) | `"Explanatory"` |

157| `forceLoginMethod` | Use `claudeai` to restrict login to Claude.ai accounts, `console` to restrict login to Claude Console (API usage billing) accounts | `claudeai` |211| `permissions` | See table below for structure of permissions. | |

158| `forceLoginOrgUUID` | Specify the UUID of an organization to automatically select it during login, bypassing the organization selection step. Requires `forceLoginMethod` to be set | `"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` |

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

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

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

162| `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" }]` |

163| `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" }]` |

164| `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" }]` |

165| `awsAuthRefresh` | Custom script that modifies the `.aws` directory (see [advanced credential configuration](/en/amazon-bedrock#advanced-credential-configuration)) | `aws sso login --profile myprofile` |

166| `awsCredentialExport` | Custom script that outputs JSON with AWS credentials (see [advanced credential configuration](/en/amazon-bedrock#advanced-credential-configuration)) | `/bin/generate_aws_grant.sh` |

167| `alwaysThinkingEnabled` | Enable [extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) by default for all sessions. Typically configured via the `/config` command rather than editing directly | `true` |

168| `plansDirectory` | Customize where plan files are stored. Path is relative to project root. Default: `~/.claude/plans` | `"./plans"` |212| `plansDirectory` | Customize where plan files are stored. Path is relative to project root. Default: `~/.claude/plans` | `"./plans"` |

169| `showTurnDuration` | Show turn duration messages after responses (e.g., "Cooked for 1m 6s"). Set to `false` to hide these messages | `true` |213| `pluginTrustMessage` | (Managed settings only) Custom message appended to the plugin trust warning shown before installation. Use this to add organization-specific context, for example to confirm that plugins from your internal marketplace are vetted. | `"All plugins from our marketplace are approved by IT"` |

170| `spinnerVerbs` | Customize the action verbs shown in the spinner and turn duration messages. Set `mode` to `"replace"` to use only your verbs, or `"append"` to add them to the defaults | `{"mode": "append", "verbs": ["Pondering", "Crafting"]}` |214| `prefersReducedMotion` | Reduce or disable UI animations (spinners, shimmer, flash effects) for accessibility | `true` |

171| `language` | Configure Claude's preferred response language (e.g., `"japanese"`, `"spanish"`, `"french"`). Claude will respond in this language by default | `"japanese"` |215| `prUrlTemplate` | URL template for the PR badge shown in the footer and in tool-result summaries. Substitutes `{host}`, `{owner}`, `{repo}`, `{number}`, and `{url}` from the `gh`-reported PR URL. Use to point PR links at an internal code-review tool instead of `github.com`. Does not affect `#123` autolinks in Claude's prose | `"https://reviews.example.com/{owner}/{repo}/pull/{number}"` |

172| `autoUpdatesChannel` | Release channel to follow for updates. Use `"stable"` for a version that is typically about one week old and skips versions with major regressions, or `"latest"` (default) for the most recent release | `"stable"` |216| `respectGitignore` | Control whether the `@` file picker respects `.gitignore` patterns. When `true` (default), files matching `.gitignore` patterns are excluded from suggestions | `false` |

217| `showClearContextOnPlanAccept` | Show the "clear context" option on the plan accept screen. Defaults to `false`. Set to `true` to restore the option | `true` |

218| `showThinkingSummaries` | Show [extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) summaries in interactive sessions. When unset or `false` (default in interactive mode), thinking blocks are redacted by the API and shown as a collapsed stub. Redaction only changes what you see, not what the model generates: to reduce thinking spend, [lower the budget or disable thinking](/en/common-workflows#use-extended-thinking-thinking-mode) instead. Non-interactive mode (`-p`) and SDK callers always receive summaries regardless of this setting | `true` |

219| `showTurnDuration` | Show turn duration messages after responses, e.g. "Cooked for 1m 6s". Default: `true`. Appears in `/config` as **Show turn duration** | `false` |

220| `skipWebFetchPreflight` | Skip the [WebFetch domain safety check](/en/data-usage#webfetch-domain-safety-check) that sends each requested hostname to `api.anthropic.com` before fetching. Set to `true` in environments that block traffic to Anthropic, such as Bedrock, Vertex AI, or Foundry deployments with restrictive egress. When skipped, WebFetch attempts any URL without consulting the blocklist | `true` |

173| `spinnerTipsEnabled` | Show tips in the spinner while Claude is working. Set to `false` to disable tips (default: `true`) | `false` |221| `spinnerTipsEnabled` | Show tips in the spinner while Claude is working. Set to `false` to disable tips (default: `true`) | `false` |

174| `terminalProgressBarEnabled` | Enable the terminal progress bar that shows progress in supported terminals like Windows Terminal and iTerm2 (default: `true`) | `false` |222| `spinnerTipsOverride` | Override spinner tips with custom strings. `tips`: array of tip strings. `excludeDefault`: if `true`, only show custom tips; if `false` or absent, custom tips are merged with built-in tips | `{ "excludeDefault": true, "tips": ["Use our internal tool X"] }` |

175 223| `spinnerVerbs` | Customize the action verbs shown in the spinner and turn duration messages. Set `mode` to `"replace"` to use only your verbs, or `"append"` to add them to the defaults | `{"mode": "append", "verbs": ["Pondering", "Crafting"]}` |

176### Permission settings224| `sshConfigs` | SSH connections to show in the [Desktop](/en/desktop#pre-configure-ssh-connections-for-your-team) environment dropdown. Each entry requires `id`, `name`, and `sshHost`; `sshPort`, `sshIdentityFile`, and `startDirectory` are optional. When set in managed settings, connections are read-only for users. Read from managed and user settings only | `[{"id": "dev-vm", "name": "Dev VM", "sshHost": "user@dev.example.com"}]` |

225| `statusLine` | Configure a custom status line to display context. See [`statusLine` documentation](/en/statusline) | `{"type": "command", "command": "~/.claude/statusline.sh"}` |

226| `strictKnownMarketplaces` | (Managed settings only) Allowlist of plugin marketplace sources. Undefined = no restrictions, empty array = lockdown. Enforced on marketplace add and on plugin install, update, refresh, and auto-update, so a marketplace added before the policy was set cannot be used to fetch plugins. See [Managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) | `[{ "source": "github", "repo": "acme-corp/plugins" }]` |

227| `teammateMode` | How [agent team](/en/agent-teams) teammates display: `auto` (picks split panes in tmux or iTerm2, in-process otherwise), `in-process`, or `tmux`. See [choose a display mode](/en/agent-teams#choose-a-display-mode) | `"in-process"` |

228| `terminalProgressBarEnabled` | Show the terminal progress bar in supported terminals: ConEmu, Ghostty 1.2.0+, and iTerm2 3.6.6+. Default: `true`. Appears in `/config` as **Terminal progress bar** | `false` |

229| `tui` | Terminal UI renderer. Use `"fullscreen"` for the flicker-free [alt-screen renderer](/en/fullscreen) with virtualized scrollback. Use `"default"` for the classic main-screen renderer. Set via `/tui` | `"fullscreen"` |

230| `useAutoModeDuringPlan` | Whether plan mode uses auto mode semantics when auto mode is available. Default: `true`. Not read from shared project settings. Appears in `/config` as "Use auto mode during plan" | `false` |

231| `viewMode` | Default transcript view mode on startup: `"default"`, `"verbose"`, or `"focus"`. Overrides the sticky `/focus` selection when set | `"verbose"` |

232| `voice` | [Voice dictation](/en/voice-dictation) settings: `enabled` turns dictation on, `mode` selects `"hold"` or `"tap"`, and `autoSubmit` sends the prompt on key release in hold mode. Written automatically when you run `/voice`. Requires a Claude.ai account | `{ "enabled": true, "mode": "tap" }` |

233| `voiceEnabled` | Legacy alias for `voice.enabled`. Prefer the `voice` object | `true` |

234| `wslInheritsWindowsSettings` | (Windows managed settings only) When `true`, Claude Code on WSL reads managed settings from the Windows policy chain in addition to `/etc/claude-code`, with Windows sources taking priority. Only honored when set in the HKLM registry key or `C:\Program Files\ClaudeCode\managed-settings.json`, both of which require Windows admin to write. For HKCU policy to also apply on WSL, the flag must additionally be set in HKCU itself. Has no effect on native Windows | `true` |

177 235 

178| Keys | Description | Example |236### Global config settings

179| :----------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------- |

180| `allow` | Array of permission rules to allow tool use. See [Permission rule syntax](#permission-rule-syntax) below for pattern matching details | `[ "Bash(git diff *)" ]` |

181| `ask` | Array of permission rules to ask for confirmation upon tool use. See [Permission rule syntax](#permission-rule-syntax) below | `[ "Bash(git push *)" ]` |

182| `deny` | Array of permission rules to deny tool use. Use this to exclude sensitive files from Claude Code access. See [Permission rule syntax](#permission-rule-syntax) and [Bash permission limitations](/en/iam#tool-specific-permission-rules) | `[ "WebFetch", "Bash(curl *)", "Read(./.env)", "Read(./secrets/**)" ]` |

183| `additionalDirectories` | Additional [working directories](/en/iam#working-directories) that Claude has access to | `[ "../docs/" ]` |

184| `defaultMode` | Default [permission mode](/en/iam#permission-modes) when opening Claude Code | `"acceptEdits"` |

185| `disableBypassPermissionsMode` | Set to `"disable"` to prevent `bypassPermissions` mode from being activated. This disables the `--dangerously-skip-permissions` command-line flag. See [managed settings](/en/iam#managed-settings) | `"disable"` |

186 237 

187### Permission rule syntax238These settings are stored in `~/.claude.json` rather than `settings.json`. Adding them to `settings.json` will trigger a schema validation error.

188 239 

189Permission rules follow the format `Tool` or `Tool(specifier)`. Understanding the syntax helps you write rules that match exactly what you intend.240<Note>

241 Versions before v2.1.119 also store `autoScrollEnabled`, `editorMode`, `showTurnDuration`, `teammateMode`, and `terminalProgressBarEnabled` here instead of in `settings.json`.

242</Note>

190 243 

191#### Rule evaluation order244| Key | Description | Example |

245| :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ |

246| `autoConnectIde` | Automatically connect to a running IDE when Claude Code starts from an external terminal. Default: `false`. Appears in `/config` as **Auto-connect to IDE (external terminal)** when running outside a VS Code or JetBrains terminal | `true` |

247| `autoInstallIdeExtension` | Automatically install the Claude Code IDE extension when running from a VS Code terminal. Default: `true`. Appears in `/config` as **Auto-install IDE extension** when running inside a VS Code or JetBrains terminal. You can also set the [`CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL`](/en/env-vars) environment variable | `false` |

248| `externalEditorContext` | Prepend Claude's previous response as `#`-commented context when you open the external editor with `Ctrl+G`. Default: `false`. Appears in `/config` as **Show last response in external editor** | `true` |

192 249 

193When multiple rules could match the same tool use, rules are evaluated in this order:250### Worktree settings

194 251 

1951. **Deny** rules are checked first252Configure how `--worktree` creates and manages git worktrees. Use these settings to reduce disk usage and startup time in large monorepos.

1962. **Ask** rules are checked second

1973. **Allow** rules are checked last

198 253 

199The first matching rule determines the behavior. This means deny rules always take precedence over allow rules, even if both match the same command.254| Key | Description | Example |

255| :---------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------ |

256| `worktree.symlinkDirectories` | Directories to symlink from the main repository into each worktree to avoid duplicating large directories on disk. No directories are symlinked by default | `["node_modules", ".cache"]` |

257| `worktree.sparsePaths` | Directories to check out in each worktree via git sparse-checkout (cone mode). Only the listed paths are written to disk, which is faster in large monorepos | `["packages/my-app", "shared/utils"]` |

200 258 

201#### Matching all uses of a tool259To copy gitignored files like `.env` into new worktrees, use a [`.worktreeinclude` file](/en/common-workflows#copy-gitignored-files-to-worktrees) in your project root instead of a setting.

202 260 

203To match all uses of a tool, use just the tool name without parentheses:261### Permission settings

204 262 

205| Rule | Effect |263| Keys | Description | Example |

206| :--------- | :--------------------------------- |264| :---------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------- |

207| `Bash` | Matches **all** Bash commands |265| `allow` | Array of permission rules to allow tool use. See [Permission rule syntax](#permission-rule-syntax) below for pattern matching details | `[ "Bash(git diff *)" ]` |

208| `WebFetch` | Matches **all** web fetch requests |266| `ask` | Array of permission rules to ask for confirmation upon tool use. See [Permission rule syntax](#permission-rule-syntax) below | `[ "Bash(git push *)" ]` |

209| `Read` | Matches **all** file reads |267| `deny` | Array of permission rules to deny tool use. Use this to exclude sensitive files from Claude Code access. See [Permission rule syntax](#permission-rule-syntax) and [Bash permission limitations](/en/permissions#tool-specific-permission-rules) | `[ "WebFetch", "Bash(curl *)", "Read(./.env)", "Read(./secrets/**)" ]` |

268| `additionalDirectories` | Additional [working directories](/en/permissions#working-directories) for file access. Most `.claude/` configuration is [not discovered](/en/permissions#additional-directories-grant-file-access-not-configuration) from these directories | `[ "../docs/" ]` |

269| `defaultMode` | Default [permission mode](/en/permission-modes) when opening Claude Code. Valid values: `default`, `acceptEdits`, `plan`, `auto`, `dontAsk`, `bypassPermissions`. The `--permission-mode` CLI flag overrides this setting for a single session | `"acceptEdits"` |

270| `disableBypassPermissionsMode` | Set to `"disable"` to prevent `bypassPermissions` mode from being activated. This disables the `--dangerously-skip-permissions` command-line flag. Typically placed in [managed settings](/en/permissions#managed-settings) to enforce organizational policy, but works from any scope | `"disable"` |

271| `skipDangerousModePermissionPrompt` | Skip the confirmation prompt shown before entering bypass permissions mode via `--dangerously-skip-permissions` or `defaultMode: "bypassPermissions"`. Ignored when set in project settings (`.claude/settings.json`) to prevent untrusted repositories from auto-bypassing the prompt | `true` |

210 272 

211`Bash(*)` is equivalent to `Bash` and matches all Bash commands. Both syntaxes can be used interchangeably.273### Permission rule syntax

212 274 

213#### Using specifiers for fine-grained control275Permission rules follow the format `Tool` or `Tool(specifier)`. Rules are evaluated in order: deny rules first, then ask, then allow. The first matching rule wins.

214 276 

215Add a specifier in parentheses to match specific tool uses:277Quick examples:

216 278 

217| Rule | Effect |279| Rule | Effect |

218| :----------------------------- | :------------------------------------------------------- |280| :----------------------------- | :--------------------------------------- |

219| `Bash(npm run build)` | Matches the exact command `npm run build` |281| `Bash` | Matches all Bash commands |

220| `Read(./.env)` | Matches reading the `.env` file in the current directory |282| `Bash(npm run *)` | Matches commands starting with `npm run` |

283| `Read(./.env)` | Matches reading the `.env` file |

221| `WebFetch(domain:example.com)` | Matches fetch requests to example.com |284| `WebFetch(domain:example.com)` | Matches fetch requests to example.com |

222 285 

223#### Wildcard patterns286For the complete rule syntax reference, including wildcard behavior, tool-specific patterns for Read, Edit, WebFetch, MCP, and Agent rules, and security limitations of Bash patterns, see [Permission rule syntax](/en/permissions#permission-rule-syntax).

224 

225Bash rules support glob patterns with `*`. Wildcards can appear at any position in the command, including at the beginning, middle, or end. The following configuration allows npm and git commit commands while blocking git push:

226 

227```json theme={null}

228{

229 "permissions": {

230 "allow": [

231 "Bash(npm run *)",

232 "Bash(git commit *)",

233 "Bash(git * main)",

234 "Bash(* --version)",

235 "Bash(* --help *)"

236 ],

237 "deny": [

238 "Bash(git push *)"

239 ]

240 }

241}

242```

243 

244The space before `*` matters: `Bash(ls *)` matches `ls -la` but not `lsof`, while `Bash(ls*)` matches both. The legacy `:*` suffix syntax (e.g., `Bash(npm run:*)`) is equivalent to ` *` but is deprecated.

245 

246<Warning>

247 Bash permission patterns that try to constrain command arguments are fragile. For example, `Bash(curl http://github.com/ *)` intends to restrict curl to GitHub URLs, but won't match `curl -X GET http://github.com/...` (flags before URL), `curl https://github.com/...` (different protocol), or commands using shell variables. Do not rely on argument-constraining patterns as a security boundary. See [Bash permission limitations](/en/iam#tool-specific-permission-rules) for alternatives.

248</Warning>

249 

250For detailed information about tool-specific permission patterns—including Read, Edit, WebFetch, MCP, Task rules, and Bash permission limitations—see [Tool-specific permission rules](/en/iam#tool-specific-permission-rules).

251 287 

252### Sandbox settings288### Sandbox settings

253 289 

254Configure advanced sandboxing behavior. Sandboxing isolates bash commands from your filesystem and network. See [Sandboxing](/en/sandboxing) for details.290Configure advanced sandboxing behavior. Sandboxing isolates bash commands from your filesystem and network. See [Sandboxing](/en/sandboxing) for details.

255 291 

256**Filesystem and network restrictions** are configured via Read, Edit, and WebFetch permission rules, not via these sandbox settings.

257 

258| Keys | Description | Example |292| Keys | Description | Example |

259| :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------ |293| :------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------- |

260| `enabled` | Enable bash sandboxing (macOS, Linux, and WSL2). Default: false | `true` |294| `enabled` | Enable bash sandboxing (macOS, Linux, and WSL2). Default: false | `true` |

295| `failIfUnavailable` | Exit with an error at startup if `sandbox.enabled` is true but the sandbox cannot start (missing dependencies or unsupported platform). When false (default), a warning is shown and commands run unsandboxed. Intended for managed settings deployments that require sandboxing as a hard gate | `true` |

261| `autoAllowBashIfSandboxed` | Auto-approve bash commands when sandboxed. Default: true | `true` |296| `autoAllowBashIfSandboxed` | Auto-approve bash commands when sandboxed. Default: true | `true` |

262| `excludedCommands` | Commands that should run outside of the sandbox | `["git", "docker"]` |297| `excludedCommands` | Commands that should run outside of the sandbox | `["docker *"]` |

263| `allowUnsandboxedCommands` | Allow commands to run outside the sandbox via the `dangerouslyDisableSandbox` parameter. When set to `false`, the `dangerouslyDisableSandbox` escape hatch is completely disabled and all commands must run sandboxed (or be in `excludedCommands`). Useful for enterprise policies that require strict sandboxing. Default: true | `false` |298| `allowUnsandboxedCommands` | Allow commands to run outside the sandbox via the `dangerouslyDisableSandbox` parameter. When set to `false`, the `dangerouslyDisableSandbox` escape hatch is completely disabled and all commands must run sandboxed (or be in `excludedCommands`). Useful for enterprise policies that require strict sandboxing. Default: true | `false` |

264| `network.allowUnixSockets` | Unix socket paths accessible in sandbox (for SSH agents, etc.) | `["~/.ssh/agent-socket"]` |299| `filesystem.allowWrite` | Additional paths where sandboxed commands can write. Arrays are merged across all settings scopes: user, project, and managed paths are combined, not replaced. Also merged with paths from `Edit(...)` allow permission rules. See [path prefixes](#sandbox-path-prefixes) below. | `["/tmp/build", "~/.kube"]` |

265| `network.allowAllUnixSockets` | Allow all Unix socket connections in sandbox. Default: false | `true` |300| `filesystem.denyWrite` | Paths where sandboxed commands cannot write. Arrays are merged across all settings scopes. Also merged with paths from `Edit(...)` deny permission rules. | `["/etc", "/usr/local/bin"]` |

301| `filesystem.denyRead` | Paths where sandboxed commands cannot read. Arrays are merged across all settings scopes. Also merged with paths from `Read(...)` deny permission rules. | `["~/.aws/credentials"]` |

302| `filesystem.allowRead` | Paths to re-allow reading within `denyRead` regions. Takes precedence over `denyRead`. Arrays are merged across all settings scopes. Use this to create workspace-only read access patterns. | `["."]` |

303| `filesystem.allowManagedReadPathsOnly` | (Managed settings only) Only `filesystem.allowRead` paths from managed settings are respected. `denyRead` still merges from all sources. Default: false | `true` |

304| `network.allowUnixSockets` | (macOS only) Unix socket paths accessible in sandbox. Ignored on Linux and WSL2, where the seccomp filter cannot inspect socket paths; use `allowAllUnixSockets` instead. | `["~/.ssh/agent-socket"]` |

305| `network.allowAllUnixSockets` | Allow all Unix socket connections in sandbox. On Linux and WSL2 this is the only way to permit Unix sockets, since it skips the seccomp filter that otherwise blocks `socket(AF_UNIX, ...)` calls. Default: false | `true` |

266| `network.allowLocalBinding` | Allow binding to localhost ports (macOS only). Default: false | `true` |306| `network.allowLocalBinding` | Allow binding to localhost ports (macOS only). Default: false | `true` |

307| `network.allowMachLookup` | Additional XPC/Mach service names the sandbox may look up (macOS only). Supports a single trailing `*` for prefix matching. Needed for tools that communicate via XPC such as the iOS Simulator or Playwright. | `["com.apple.coresimulator.*"]` |

267| `network.allowedDomains` | Array of domains to allow for outbound network traffic. Supports wildcards (e.g., `*.example.com`). | `["github.com", "*.npmjs.org"]` |308| `network.allowedDomains` | Array of domains to allow for outbound network traffic. Supports wildcards (e.g., `*.example.com`). | `["github.com", "*.npmjs.org"]` |

309| `network.deniedDomains` | Array of domains to block for outbound network traffic. Supports the same wildcard syntax as `allowedDomains`. Takes precedence over `allowedDomains` when both match. Merged from all settings sources regardless of `allowManagedDomainsOnly`. | `["sensitive.cloud.example.com"]` |

310| `network.allowManagedDomainsOnly` | (Managed settings only) Only `allowedDomains` and `WebFetch(domain:...)` allow rules from managed settings are respected. Domains from user, project, and local settings are ignored. Non-allowed domains are blocked automatically without prompting the user. Denied domains are still respected from all sources. Default: false | `true` |

268| `network.httpProxyPort` | HTTP proxy port used if you wish to bring your own proxy. If not specified, Claude will run its own proxy. | `8080` |311| `network.httpProxyPort` | HTTP proxy port used if you wish to bring your own proxy. If not specified, Claude will run its own proxy. | `8080` |

269| `network.socksProxyPort` | SOCKS5 proxy port used if you wish to bring your own proxy. If not specified, Claude will run its own proxy. | `8081` |312| `network.socksProxyPort` | SOCKS5 proxy port used if you wish to bring your own proxy. If not specified, Claude will run its own proxy. | `8081` |

270| `enableWeakerNestedSandbox` | Enable weaker sandbox for unprivileged Docker environments (Linux and WSL2 only). **Reduces security.** Default: false | `true` |313| `enableWeakerNestedSandbox` | Enable weaker sandbox for unprivileged Docker environments (Linux and WSL2 only). **Reduces security.** Default: false | `true` |

314| `enableWeakerNetworkIsolation` | (macOS only) Allow access to the system TLS trust service (`com.apple.trustd.agent`) in the sandbox. Required for Go-based tools like `gh`, `gcloud`, and `terraform` to verify TLS certificates when using `httpProxyPort` with a MITM proxy and custom CA. **Reduces security** by opening a potential data exfiltration path. Default: false | `true` |

315 

316#### Sandbox path prefixes

317 

318Paths in `filesystem.allowWrite`, `filesystem.denyWrite`, `filesystem.denyRead`, and `filesystem.allowRead` support these prefixes:

319 

320| Prefix | Meaning | Example |

321| :---------------- | :------------------------------------------------------------------------------------- | :------------------------------------------------------------------------ |

322| `/` | Absolute path from filesystem root | `/tmp/build` stays `/tmp/build` |

323| `~/` | Relative to home directory | `~/.kube` becomes `$HOME/.kube` |

324| `./` or no prefix | Relative to the project root for project settings, or to `~/.claude` for user settings | `./output` in `.claude/settings.json` resolves to `<project-root>/output` |

325 

326The older `//path` prefix for absolute paths still works. If you previously used single-slash `/path` expecting project-relative resolution, switch to `./path`. This syntax differs from [Read and Edit permission rules](/en/permissions#read-and-edit), which use `//path` for absolute and `/path` for project-relative. Sandbox filesystem paths use standard conventions: `/tmp/build` is an absolute path.

271 327 

272**Configuration example:**328**Configuration example:**

273 329 


276 "sandbox": {332 "sandbox": {

277 "enabled": true,333 "enabled": true,

278 "autoAllowBashIfSandboxed": true,334 "autoAllowBashIfSandboxed": true,

279 "excludedCommands": ["docker"],335 "excludedCommands": ["docker *"],

336 "filesystem": {

337 "allowWrite": ["/tmp/build", "~/.kube"],

338 "denyRead": ["~/.aws/credentials"]

339 },

280 "network": {340 "network": {

281 "allowedDomains": ["github.com", "*.npmjs.org", "registry.yarnpkg.com"],341 "allowedDomains": ["github.com", "*.npmjs.org", "registry.yarnpkg.com"],

342 "deniedDomains": ["uploads.github.com"],

282 "allowUnixSockets": [343 "allowUnixSockets": [

283 "/var/run/docker.sock"344 "/var/run/docker.sock"

284 ],345 ],

285 "allowLocalBinding": true346 "allowLocalBinding": true

286 }347 }

287 },

288 "permissions": {

289 "deny": [

290 "Read(.envrc)",

291 "Read(~/.aws/**)"

292 ]

293 }348 }

294}349}

295```350```

296 351 

297**Filesystem and network restrictions** use standard permission rules:352**Filesystem and network restrictions** can be configured in two ways that are merged together:

298 353 

299* Use `Read` deny rules to block Claude from reading specific files or directories354* **`sandbox.filesystem` settings** (shown above): Control paths at the OS-level sandbox boundary. These restrictions apply to all subprocess commands (e.g., `kubectl`, `terraform`, `npm`), not just Claude's file tools.

300* Use `Edit` allow rules to let Claude write to directories beyond the current working directory355* **Permission rules**: Use `Edit` allow/deny rules to control Claude's file tool access, `Read` deny rules to block reads, and `WebFetch` allow/deny rules to control network domains. Paths from these rules are also merged into the sandbox configuration.

301* Use `Edit` deny rules to block writes to specific paths

302* Use `WebFetch` allow/deny rules to control which network domains Claude can access

303 356 

304### Attribution settings357### Attribution settings

305 358 


315 368 

316**Default commit attribution:**369**Default commit attribution:**

317 370 

318```371```text theme={null}

319🤖 Generated with [Claude Code](https://claude.com/claude-code)372🤖 Generated with [Claude Code](https://claude.com/claude-code)

320 373 

321 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>374 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

322```375```

323 376 

324**Default pull request attribution:**377**Default pull request attribution:**

325 378 

326```379```text theme={null}

327🤖 Generated with [Claude Code](https://claude.com/claude-code)380🤖 Generated with [Claude Code](https://claude.com/claude-code)

328```381```

329 382 


363 416 

364Output newline-separated file paths to stdout (currently limited to 15):417Output newline-separated file paths to stdout (currently limited to 15):

365 418 

366```419```text theme={null}

367src/components/Button.tsx420src/components/Button.tsx

368src/components/Modal.tsx421src/components/Modal.tsx

369src/components/Form.tsx422src/components/Form.tsx


379 432 

380### Hook configuration433### Hook configuration

381 434 

382**Managed settings only**: Controls which hooks are allowed to run. This setting can only be configured in [managed settings](#settings-files) and provides administrators with strict control over hook execution.435These settings control which hooks are allowed to run and what HTTP hooks can access. The `allowManagedHooksOnly` setting can only be configured in [managed settings](#settings-files). The URL and env var allowlists can be set at any settings level and merge across sources.

383 436 

384**Behavior when `allowManagedHooksOnly` is `true`:**437**Behavior when `allowManagedHooksOnly` is `true`:**

385 438 

386* Managed hooks and SDK hooks are loaded439* Managed hooks and SDK hooks are loaded

387* User hooks, project hooks, and plugin hooks are blocked440* Hooks from plugins force-enabled in managed settings `enabledPlugins` are loaded. This lets administrators distribute vetted hooks through an organization marketplace while blocking everything else. Trust is granted by full `plugin@marketplace` ID, so a plugin with the same name from a different marketplace stays blocked

441* User hooks, project hooks, and all other plugin hooks are blocked

442 

443**Restrict HTTP hook URLs:**

388 444 

389**Configuration:**445Limit which URLs HTTP hooks can target. Supports `*` as a wildcard for matching. When the array is defined, HTTP hooks targeting non-matching URLs are silently blocked.

390 446 

391```json theme={null}447```json theme={null}

392{448{

393 "allowManagedHooksOnly": true449 "allowedHttpHookUrls": ["https://hooks.example.com/*", "http://localhost:*"]

450}

451```

452 

453**Restrict HTTP hook environment variables:**

454 

455Limit which environment variable names HTTP hooks can interpolate into header values. Each hook's effective `allowedEnvVars` is the intersection of its own list and this setting.

456 

457```json theme={null}

458{

459 "httpHookAllowedEnvVars": ["MY_TOKEN", "HOOK_SECRET"]

394}460}

395```461```

396 462 


398 464 

399Settings apply in order of precedence. From highest to lowest:465Settings apply in order of precedence. From highest to lowest:

400 466 

4011. **Managed settings** (`managed-settings.json`)4671. **Managed settings** ([server-managed](/en/server-managed-settings), [MDM/OS-level policies](#configuration-scopes), or [managed settings](/en/settings#settings-files))

402 * Policies deployed by IT/DevOps to system directories468 * Policies deployed by IT through server delivery, MDM configuration profiles, registry policies, or managed settings files

403 * Cannot be overridden by user or project settings469 * Cannot be overridden by any other level, including command line arguments

470 * Within the managed tier, precedence is: server-managed > MDM/OS-level policies > file-based (`managed-settings.d/*.json` + `managed-settings.json`) > HKCU registry (Windows only). Only one managed source is used; sources do not merge across tiers. Within the file-based tier, drop-in files and the base file are merged together.

404 471 

4052. **Command line arguments**4722. **Command line arguments**

406 * Temporary overrides for a specific session473 * Temporary overrides for a specific session


4145. **User settings** (`~/.claude/settings.json`)4815. **User settings** (`~/.claude/settings.json`)

415 * Personal global settings482 * Personal global settings

416 483 

417This hierarchy ensures that organizational policies are always enforced while still allowing teams and individuals to customize their experience.484This hierarchy ensures that organizational policies are always enforced while still allowing teams and individuals to customize their experience. The same precedence applies whether you run Claude Code from the CLI, the [VS Code extension](/en/vs-code), or a [JetBrains IDE](/en/jetbrains).

418 485 

419For example, if your user settings allow `Bash(npm run *)` but a project's shared settings deny it, the project setting takes precedence and the command is blocked.486For example, if your user settings allow `Bash(npm run *)` but a project's shared settings deny it, the project setting takes precedence and the command is blocked.

420 487 

488<Note>

489 **Array settings merge across scopes.** When the same array-valued setting (such as `sandbox.filesystem.allowWrite` or `permissions.allow`) appears in multiple scopes, the arrays are **concatenated and deduplicated**, not replaced. This means lower-priority scopes can add entries without overriding those set by higher-priority scopes, and vice versa. For example, if managed settings set `allowWrite` to `["/opt/company-tools"]` and a user adds `["~/.kube"]`, both paths are included in the final configuration.

490</Note>

491 

492### Verify active settings

493 

494Run `/status` inside Claude Code to see which settings sources are active and where they come from. The output shows each configuration layer (managed, user, project) along with its origin, such as `Enterprise managed settings (remote)`, `Enterprise managed settings (plist)`, `Enterprise managed settings (HKLM)`, `Enterprise managed settings (HKCU)`, or `Enterprise managed settings (file)`. If a settings file contains errors, `/status` reports the issue so you can fix it.

495 

421### Key points about the configuration system496### Key points about the configuration system

422 497 

423* **Memory files (`CLAUDE.md`)**: Contain instructions and context that Claude loads at startup498* **Memory files (`CLAUDE.md`)**: Contain instructions and context that Claude loads at startup


493* **User settings** (`~/.claude/settings.json`): Personal plugin preferences568* **User settings** (`~/.claude/settings.json`): Personal plugin preferences

494* **Project settings** (`.claude/settings.json`): Project-specific plugins shared with team569* **Project settings** (`.claude/settings.json`): Project-specific plugins shared with team

495* **Local settings** (`.claude/settings.local.json`): Per-machine overrides (not committed)570* **Local settings** (`.claude/settings.local.json`): Per-machine overrides (not committed)

571* **Managed settings** (`managed-settings.json`): Organization-wide policy overrides that block installation at all scopes and hide the plugin from the marketplace

496 572 

497**Example**:573**Example**:

498 574 


544* `git`: Any git URL (uses `url`)620* `git`: Any git URL (uses `url`)

545* `directory`: Local filesystem path (uses `path`, for development only)621* `directory`: Local filesystem path (uses `path`, for development only)

546* `hostPattern`: regex pattern to match marketplace hosts (uses `hostPattern`)622* `hostPattern`: regex pattern to match marketplace hosts (uses `hostPattern`)

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

624 

625Use `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`.

626 

627```json theme={null}

628{

629 "extraKnownMarketplaces": {

630 "team-tools": {

631 "source": {

632 "source": "settings",

633 "name": "team-tools",

634 "plugins": [

635 {

636 "name": "code-formatter",

637 "source": {

638 "source": "github",

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

640 }

641 }

642 ]

643 }

644 }

645 }

646}

647```

547 648 

548#### `strictKnownMarketplaces`649#### `strictKnownMarketplaces`

549 650 

550**Managed settings only**: Controls which plugin marketplaces users are allowed to add. This setting can only be configured in [`managed-settings.json`](/en/iam#managed-settings) and provides administrators with strict control over marketplace sources.651**Managed settings only**: Controls which plugin marketplaces users are allowed to add and install plugins from. This setting can only be configured in [managed settings](/en/settings#settings-files) and provides administrators with strict control over marketplace sources.

551 652 

552**Managed settings file locations**:653**Managed settings file locations**:

553 654 


570 671 

571**All supported source types**:672**All supported source types**:

572 673 

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

574 675 

5751. **GitHub repositories**:6761. **GitHub repositories**:

576 677 


755}856}

756```857```

757 858 

859**Using both together**:

860 

861`strictKnownMarketplaces` is a policy gate: it controls what users may add but does not register any marketplaces. To both restrict and pre-register a marketplace for all users, set both in `managed-settings.json`:

862 

863```json theme={null}

864{

865 "strictKnownMarketplaces": [

866 { "source": "github", "repo": "acme-corp/plugins" }

867 ],

868 "extraKnownMarketplaces": {

869 "acme-tools": {

870 "source": { "source": "github", "repo": "acme-corp/plugins" }

871 }

872 }

873}

874```

875 

876With only `strictKnownMarketplaces` set, users can still add the allowed marketplace manually via `/plugin marketplace add`, but it is not available automatically.

877 

758**Important notes**:878**Important notes**:

759 879 

760* Restrictions are checked BEFORE any network requests or filesystem operations880* Restrictions are checked BEFORE any network requests or filesystem operations

761* When blocked, users see clear error messages indicating the source is blocked by managed policy881* When blocked, users see clear error messages indicating the source is blocked by managed policy

762* The restriction applies only to adding NEW marketplaces; previously installed marketplaces remain accessible882* The restriction is enforced on marketplace add and on plugin install, update, refresh, and auto-update. A marketplace added before the policy was set cannot be used to install or update plugins once its source no longer matches the allowlist

763* Managed settings have the highest precedence and cannot be overridden883* Managed settings have the highest precedence and cannot be overridden

764 884 

765See [Managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) for user-facing documentation.885See [Managed marketplace restrictions](/en/plugin-marketplaces#managed-marketplace-restrictions) for user-facing documentation.


771* Browse available plugins from marketplaces891* Browse available plugins from marketplaces

772* Install/uninstall plugins892* Install/uninstall plugins

773* Enable/disable plugins893* Enable/disable plugins

774* View plugin details (commands, agents, hooks provided)894* View plugin details (skills, agents, hooks provided)

775* Add/remove marketplaces895* Add/remove marketplaces

776 896 

777Learn more about the plugin system in the [plugins documentation](/en/plugins).897Learn more about the plugin system in the [plugins documentation](/en/plugins).

778 898 

779## Environment variables899## Environment variables

780 900 

781Claude Code supports the following environment variables to control its behavior:901Environment variables let you control Claude Code behavior without editing settings files. Any variable can also be configured in [`settings.json`](#available-settings) under the `env` key to apply it to every session or roll it out to your team.

782 902 

783<Note>903See the [environment variables reference](/en/env-vars) for the full list.

784 All environment variables can also be configured in [`settings.json`](#available-settings). This is useful as a way to automatically set environment variables for each session, or to roll out a set of environment variables for your whole team or organization.

785</Note>

786 

787| Variable | Purpose | |

788| :--------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- |

789| `ANTHROPIC_API_KEY` | API key sent as `X-Api-Key` header, typically for the Claude SDK (for interactive usage, run `/login`) | |

790| `ANTHROPIC_AUTH_TOKEN` | Custom value for the `Authorization` header (the value you set here will be prefixed with `Bearer `) | |

791| `ANTHROPIC_CUSTOM_HEADERS` | Custom headers to add to requests (`Name: Value` format, newline-separated for multiple headers) | |

792| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | See [Model configuration](/en/model-config#environment-variables) | |

793| `ANTHROPIC_DEFAULT_OPUS_MODEL` | See [Model configuration](/en/model-config#environment-variables) | |

794| `ANTHROPIC_DEFAULT_SONNET_MODEL` | See [Model configuration](/en/model-config#environment-variables) | |

795| `ANTHROPIC_FOUNDRY_API_KEY` | API key for Microsoft Foundry authentication (see [Microsoft Foundry](/en/microsoft-foundry)) | |

796| `ANTHROPIC_FOUNDRY_BASE_URL` | Full base URL for the Foundry resource (for example, `https://my-resource.services.ai.azure.com/anthropic`). Alternative to `ANTHROPIC_FOUNDRY_RESOURCE` (see [Microsoft Foundry](/en/microsoft-foundry)) | |

797| `ANTHROPIC_FOUNDRY_RESOURCE` | Foundry resource name (for example, `my-resource`). Required if `ANTHROPIC_FOUNDRY_BASE_URL` is not set (see [Microsoft Foundry](/en/microsoft-foundry)) | |

798| `ANTHROPIC_MODEL` | Name of the model setting to use (see [Model Configuration](/en/model-config#environment-variables)) | |

799| `ANTHROPIC_SMALL_FAST_MODEL` | \[DEPRECATED] Name of [Haiku-class model for background tasks](/en/costs) | |

800| `ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION` | Override AWS region for the Haiku-class model when using Bedrock | |

801| `AWS_BEARER_TOKEN_BEDROCK` | Bedrock API key for authentication (see [Bedrock API keys](https://aws.amazon.com/blogs/machine-learning/accelerate-ai-development-with-amazon-bedrock-api-keys/)) | |

802| `BASH_DEFAULT_TIMEOUT_MS` | Default timeout for long-running bash commands | |

803| `BASH_MAX_OUTPUT_LENGTH` | Maximum number of characters in bash outputs before they are middle-truncated | |

804| `BASH_MAX_TIMEOUT_MS` | Maximum timeout the model can set for long-running bash commands | |

805| `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` | Set the percentage of context capacity (1-100) at which auto-compaction triggers. By default, auto-compaction triggers at approximately 95% capacity. Use lower values like `50` to compact earlier. Values above the default threshold have no effect. Applies to both main conversations and subagents. This percentage aligns with the `context_window.used_percentage` field available in [status line](/en/statusline) | |

806| `CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR` | Return to the original working directory after each Bash command | |

807| `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` | Set to `1` to load CLAUDE.md files from directories specified with `--add-dir`. By default, additional directories do not load memory files | `1` |

808| `CLAUDE_CODE_API_KEY_HELPER_TTL_MS` | Interval in milliseconds at which credentials should be refreshed (when using `apiKeyHelper`) | |

809| `CLAUDE_CODE_CLIENT_CERT` | Path to client certificate file for mTLS authentication | |

810| `CLAUDE_CODE_CLIENT_KEY_PASSPHRASE` | Passphrase for encrypted CLAUDE\_CODE\_CLIENT\_KEY (optional) | |

811| `CLAUDE_CODE_CLIENT_KEY` | Path to client private key file for mTLS authentication | |

812| `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` | Set to `1` to disable Anthropic API-specific `anthropic-beta` headers. Use this if experiencing issues like "Unexpected value(s) for the `anthropic-beta` header" when using an LLM gateway with third-party providers | |

813| `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` | Set to `1` to disable all background task functionality, including the `run_in_background` parameter on Bash and subagent tools, auto-backgrounding, and the Ctrl+B shortcut | |

814| `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 | |

815| `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 | |

816| `CLAUDE_CODE_TASK_LIST_ID` | Share a task list across sessions. Set the same ID in multiple Claude Code instances to coordinate on a shared task list. See [Task list](/en/interactive-mode#task-list) | |

817| `CLAUDE_CODE_TMPDIR` | Override the temp directory used for internal temp files. Claude Code appends `/claude/` to this path. Default: `/tmp` on Unix/macOS, `os.tmpdir()` on Windows | |

818| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | Equivalent of setting `DISABLE_AUTOUPDATER`, `DISABLE_BUG_COMMAND`, `DISABLE_ERROR_REPORTING`, and `DISABLE_TELEMETRY` | |

819| `CLAUDE_CODE_DISABLE_TERMINAL_TITLE` | Set to `1` to disable automatic terminal title updates based on conversation context | |

820| `CLAUDE_CODE_ENABLE_TASKS` | Set to `false` to temporarily revert to the previous TODO list instead of the task tracking system. Default: `true`. See [Task list](/en/interactive-mode#task-list) | |

821| `CLAUDE_CODE_ENABLE_TELEMETRY` | Set to `1` to enable OpenTelemetry data collection for metrics and logging. Required before configuring OTel exporters. See [Monitoring](/en/monitoring-usage) | |

822| `CLAUDE_CODE_FILE_READ_MAX_OUTPUT_TOKENS` | Override the default token limit for file reads. Useful when you need to read larger files in full | |

823| `CLAUDE_CODE_HIDE_ACCOUNT_INFO` | Set to `1` to hide your email address and organization name from the Claude Code UI. Useful when streaming or recording | |

824| `CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL` | Skip auto-installation of IDE extensions | |

825| `CLAUDE_CODE_MAX_OUTPUT_TOKENS` | Set the maximum number of output tokens for most requests. Default: 32,000. Maximum: 64,000. Increasing this value reduces the effective context window available before [auto-compaction](/en/costs#reduce-token-usage) triggers. | |

826| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic OpenTelemetry headers in milliseconds (default: 1740000 / 29 minutes). See [Dynamic headers](/en/monitoring-usage#dynamic-headers) | |

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

828| `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>` | |

829| `CLAUDE_CODE_SKIP_BEDROCK_AUTH` | Skip AWS authentication for Bedrock (for example, when using an LLM gateway) | |

830| `CLAUDE_CODE_SKIP_FOUNDRY_AUTH` | Skip Azure authentication for Microsoft Foundry (for example, when using an LLM gateway) | |

831| `CLAUDE_CODE_SKIP_VERTEX_AUTH` | Skip Google authentication for Vertex (for example, when using an LLM gateway) | |

832| `CLAUDE_CODE_SUBAGENT_MODEL` | See [Model configuration](/en/model-config) | |

833| `CLAUDE_CODE_USE_BEDROCK` | Use [Bedrock](/en/amazon-bedrock) | |

834| `CLAUDE_CODE_USE_FOUNDRY` | Use [Microsoft Foundry](/en/microsoft-foundry) | |

835| `CLAUDE_CODE_USE_VERTEX` | Use [Vertex](/en/google-vertex-ai) | |

836| `CLAUDE_CONFIG_DIR` | Customize where Claude Code stores its configuration and data files | |

837| `DISABLE_AUTOUPDATER` | Set to `1` to disable automatic updates. | |

838| `DISABLE_BUG_COMMAND` | Set to `1` to disable the `/bug` command | |

839| `DISABLE_COST_WARNINGS` | Set to `1` to disable cost warning messages | |

840| `DISABLE_ERROR_REPORTING` | Set to `1` to opt out of Sentry error reporting | |

841| `DISABLE_INSTALLATION_CHECKS` | Set to `1` to disable installation warnings. Use only when manually managing the installation location, as this can mask issues with standard installations | |

842| `DISABLE_NON_ESSENTIAL_MODEL_CALLS` | Set to `1` to disable model calls for non-critical paths like flavor text | |

843| `DISABLE_PROMPT_CACHING` | Set to `1` to disable prompt caching for all models (takes precedence over per-model settings) | |

844| `DISABLE_PROMPT_CACHING_HAIKU` | Set to `1` to disable prompt caching for Haiku models | |

845| `DISABLE_PROMPT_CACHING_OPUS` | Set to `1` to disable prompt caching for Opus models | |

846| `DISABLE_PROMPT_CACHING_SONNET` | Set to `1` to disable prompt caching for Sonnet models | |

847| `DISABLE_TELEMETRY` | Set to `1` to opt out of Statsig telemetry (note that Statsig events do not include user data like code, file paths, or bash commands) | |

848| `ENABLE_TOOL_SEARCH` | Controls [MCP tool search](/en/mcp#scale-with-mcp-tool-search). Values: `auto` (default, enables at 10% context), `auto:N` (custom threshold, e.g., `auto:5` for 5%), `true` (always on), `false` (disabled) | |

849| `FORCE_AUTOUPDATE_PLUGINS` | Set to `true` to force plugin auto-updates even when the main auto-updater is disabled via `DISABLE_AUTOUPDATER` | |

850| `HTTP_PROXY` | Specify HTTP proxy server for network connections | |

851| `HTTPS_PROXY` | Specify HTTPS proxy server for network connections | |

852| `IS_DEMO` | Set to `true` to enable demo mode: hides email and organization from the UI, skips onboarding, and hides internal commands. Useful for streaming or recording sessions | |

853| `MAX_MCP_OUTPUT_TOKENS` | Maximum number of tokens allowed in MCP tool responses. Claude Code displays a warning when output exceeds 10,000 tokens (default: 25000) | |

854| `MAX_THINKING_TOKENS` | Override the [extended thinking](https://docs.claude.com/en/docs/build-with-claude/extended-thinking) token budget. Thinking is enabled at max budget (31,999 tokens) by default. Use this to limit the budget (for example, `MAX_THINKING_TOKENS=10000`) or disable thinking entirely (`MAX_THINKING_TOKENS=0`). Extended thinking improves performance on complex reasoning and coding tasks but impacts [prompt caching efficiency](https://docs.claude.com/en/docs/build-with-claude/prompt-caching#caching-with-thinking-blocks). | |

855| `MCP_TIMEOUT` | Timeout in milliseconds for MCP server startup | |

856| `MCP_TOOL_TIMEOUT` | Timeout in milliseconds for MCP tool execution | |

857| `NO_PROXY` | List of domains and IPs to which requests will be directly issued, bypassing proxy | |

858| `SLASH_COMMAND_TOOL_CHAR_BUDGET` | Maximum number of characters for skill metadata shown to the [Skill tool](/en/skills#control-who-invokes-a-skill) (default: 15000). Legacy name kept for backwards compatibility. | |

859| `USE_BUILTIN_RIPGREP` | Set to `0` to use system-installed `rg` instead of `rg` included with Claude Code | |

860| `VERTEX_REGION_CLAUDE_3_5_HAIKU` | Override region for Claude 3.5 Haiku when using Vertex AI | |

861| `VERTEX_REGION_CLAUDE_3_7_SONNET` | Override region for Claude 3.7 Sonnet when using Vertex AI | |

862| `VERTEX_REGION_CLAUDE_4_0_OPUS` | Override region for Claude 4.0 Opus when using Vertex AI | |

863| `VERTEX_REGION_CLAUDE_4_0_SONNET` | Override region for Claude 4.0 Sonnet when using Vertex AI | |

864| `VERTEX_REGION_CLAUDE_4_1_OPUS` | Override region for Claude 4.1 Opus when using Vertex AI | |

865 904 

866## Tools available to Claude905## Tools available to Claude

867 906 

868Claude Code has access to a set of powerful tools that help it understand and modify your codebase:907Claude Code has access to a set of tools for reading, editing, searching, running commands, and orchestrating subagents. Tool names are the exact strings you use in permission rules and hook matchers.

869 

870| Tool | Description | Permission Required |

871| :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------ |

872| **AskUserQuestion** | Asks multiple-choice questions to gather requirements or clarify ambiguity | No |

873| **Bash** | Executes shell commands in your environment (see [Bash tool behavior](#bash-tool-behavior) below) | Yes |

874| **TaskOutput** | Retrieves output from a background task (bash shell or subagent) | No |

875| **Edit** | Makes targeted edits to specific files | Yes |

876| **ExitPlanMode** | Prompts the user to exit plan mode and start coding | Yes |

877| **Glob** | Finds files based on pattern matching | No |

878| **Grep** | Searches for patterns in file contents | No |

879| **KillShell** | Kills a running background bash shell by its ID | No |

880| **MCPSearch** | Searches for and loads MCP tools when [tool search](/en/mcp#scale-with-mcp-tool-search) is enabled | No |

881| **NotebookEdit** | Modifies Jupyter notebook cells | Yes |

882| **Read** | Reads the contents of files | No |

883| **Skill** | Executes a [skill](/en/skills#control-who-invokes-a-skill) within the main conversation | Yes |

884| **Task** | Runs a sub-agent to handle complex, multi-step tasks | No |

885| **TaskCreate** | Creates a new task in the task list | No |

886| **TaskGet** | Retrieves full details for a specific task | No |

887| **TaskList** | Lists all tasks with their current status | No |

888| **TaskUpdate** | Updates task status, dependencies, details, or deletes tasks | No |

889| **WebFetch** | Fetches content from a specified URL | Yes |

890| **WebSearch** | Performs web searches with domain filtering | Yes |

891| **Write** | Creates or overwrites files | Yes |

892| **LSP** | Code intelligence via language servers. Reports type errors and warnings automatically after file edits. Also supports navigation operations: jump to definitions, find references, get type info, list symbols, find implementations, trace call hierarchies. Requires a [code intelligence plugin](/en/discover-plugins#code-intelligence) and its language server binary | No |

893 

894Permission rules can be configured using `/allowed-tools` or in [permission settings](/en/settings#available-settings). Also see [Tool-specific permission rules](/en/iam#tool-specific-permission-rules).

895 

896### Bash tool behavior

897 

898The Bash tool executes shell commands with the following persistence behavior:

899 

900* **Working directory persists**: When Claude changes the working directory (for example, `cd /path/to/dir`), subsequent Bash commands will execute in that directory. You can use `CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1` to reset to the project directory after each command.

901* **Environment variables do NOT persist**: Environment variables set in one Bash command (for example, `export MY_VAR=value`) are **not** available in subsequent Bash commands. Each Bash command runs in a fresh shell environment.

902 

903To make environment variables available in Bash commands, you have **three options**:

904 

905**Option 1: Activate environment before starting Claude Code** (simplest approach)

906 

907Activate your virtual environment in your terminal before launching Claude Code:

908 

909```bash theme={null}

910conda activate myenv

911# or: source /path/to/venv/bin/activate

912claude

913```

914 

915This works for shell environments but environment variables set within Claude's Bash commands will not persist between commands.

916 

917**Option 2: Set CLAUDE\_ENV\_FILE before starting Claude Code** (persistent environment setup)

918 

919Export the path to a shell script containing your environment setup:

920 

921```bash theme={null}

922export CLAUDE_ENV_FILE=/path/to/env-setup.sh

923claude

924```

925 

926Where `/path/to/env-setup.sh` contains:

927 

928```bash theme={null}

929conda activate myenv

930# or: source /path/to/venv/bin/activate

931# or: export MY_VAR=value

932```

933 

934Claude Code will source this file before each Bash command, making the environment persistent across all commands.

935 

936**Option 3: Use a SessionStart hook** (project-specific configuration)

937 

938Configure in `.claude/settings.json`:

939 

940```json theme={null}

941{

942 "hooks": {

943 "SessionStart": [{

944 "matcher": "startup",

945 "hooks": [{

946 "type": "command",

947 "command": "echo 'conda activate myenv' >> \"$CLAUDE_ENV_FILE\""

948 }]

949 }]

950 }

951}

952```

953 

954The hook writes to `$CLAUDE_ENV_FILE`, which is then sourced before each Bash command. This is ideal for team-shared project configurations.

955 

956See [SessionStart hooks](/en/hooks#persist-environment-variables) for more details on Option 3.

957 

958### Extending tools with hooks

959 

960You can run custom commands before or after any tool executes using

961[Claude Code hooks](/en/hooks-guide).

962 908 

963For example, you could automatically run a Python formatter after Claude909See the [tools reference](/en/tools-reference) for the full list and Bash tool behavior details.

964modifies Python files, or prevent modifications to production configuration

965files by blocking Write operations to certain paths.

966 910 

967## See also911## See also

968 912 

969* [Identity and Access Management](/en/iam#configuring-permissions) - Permission system overview and how allow/ask/deny rules interact913* [Permissions](/en/permissions): permission system, rule syntax, tool-specific patterns, and managed policies

970* [Tool-specific permission rules](/en/iam#tool-specific-permission-rules) - Detailed patterns for Bash, Read, Edit, WebFetch, MCP, and Task tools, including security limitations914* [Authentication](/en/authentication): set up user access to Claude Code

971* [Managed settings](/en/iam#managed-settings) - Managed policy configuration for organizations915* [Debug your configuration](/en/debug-your-config): diagnose why a setting, hook, or MCP server isn't taking effect

972* [Troubleshooting](/en/troubleshooting) - Solutions for common configuration issues916* [Troubleshooting](/en/troubleshooting): installation, authentication, and platform issues

setup.md +391 −133

Details

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> 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.3> Use this file to discover all available pages before exploring further.

4 4 

5# Set up Claude Code5# Advanced setup

6 6 

7> Install, authenticate, and start using Claude Code on your development machine.7> System requirements, platform-specific installation, version management, and uninstallation for Claude Code.

8 

9This page covers system requirements, platform-specific installation details, updates, and uninstallation. For a guided walkthrough of your first session, see the [quickstart](/en/quickstart). If you've never used a terminal before, see the [terminal guide](/en/terminal-guide).

8 10 

9## System requirements11## System requirements

10 12 

11* **Operating Systems**: macOS 13.0+, Ubuntu 20.04+/Debian 10+, or Windows 10 1809+ / Windows Server 2019+ (with WSL 1, WSL 2, or Git for Windows)13Claude Code runs on the following platforms and configurations:

12* **Hardware**: 4 GB+ RAM14 

13* **Network**: Internet connection required (see [network configuration](/en/network-config#network-access-requirements))15* **Operating system**:

14* **Shell**: Works best in Bash or Zsh16 * macOS 13.0+

17 * Windows 10 1809+ or Windows Server 2019+

18 * Ubuntu 20.04+

19 * Debian 10+

20 * Alpine Linux 3.19+

21* **Hardware**: 4 GB+ RAM, x64 or ARM64 processor

22* **Network**: internet connection required. See [network configuration](/en/network-config#network-access-requirements).

23* **Shell**: Bash, Zsh, PowerShell, or CMD. Native Windows setups require [Git for Windows](https://git-scm.com/downloads/win). WSL setups do not.

15* **Location**: [Anthropic supported countries](https://www.anthropic.com/supported-countries)24* **Location**: [Anthropic supported countries](https://www.anthropic.com/supported-countries)

16 25 

17### Additional dependencies26### Additional dependencies

18 27 

19* **ripgrep**: Usually included with Claude Code. If search fails, see [search troubleshooting](/en/troubleshooting#search-and-discovery-issues).28* **ripgrep**: usually included with Claude Code. If search fails, see [search troubleshooting](/en/troubleshooting#search-and-discovery-issues).

20* **[Node.js 18+](https://nodejs.org/en/download)**: Only required for [deprecated npm installation](#npm-installation-deprecated)29 

30## Install Claude Code

21 31 

22## Installation32<Tip>

33 Prefer a graphical interface? The [Desktop app](/en/desktop-quickstart) lets you use Claude Code without the terminal. Download it for [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code\&utm_medium=docs) or [Windows](https://claude.com/download?utm_source=claude_code\&utm_medium=docs).

34 

35 New to the terminal? See the [terminal guide](/en/terminal-guide) for step-by-step instructions.

36</Tip>

23 37 

24To install Claude Code, use one of the following methods:38To install Claude Code, use one of the following methods:

25 39 


43 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd57 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd

44 ```58 ```

45 59 

60 If you see `The token '&&' is not a valid statement separator`, you're in PowerShell, not CMD. If you see `'irm' is not recognized as an internal or external command`, you're in CMD, not PowerShell. Your prompt shows `PS C:\` when you're in PowerShell and `C:\` without the `PS` when you're in CMD.

61 

62 **Native Windows setups require [Git for Windows](https://git-scm.com/downloads/win).** Install it first if you don't have it. WSL setups do not need it.

63 

46 <Info>64 <Info>

47 Native installations automatically update in the background to keep you on the latest version.65 Native installations automatically update in the background to keep you on the latest version.

48 </Info>66 </Info>

49 </Tab>67 </Tab>

50 68 

51 <Tab title="Homebrew">69 <Tab title="Homebrew">

52 ```sh theme={null}70 ```bash theme={null}

53 brew install --cask claude-code71 brew install --cask claude-code

54 ```72 ```

55 73 

74 Homebrew offers two casks. `claude-code` tracks the stable release channel, which is typically about a week behind and skips releases with major regressions. `claude-code@latest` tracks the latest channel and receives new versions as soon as they ship.

75 

56 <Info>76 <Info>

57 Homebrew installations do not auto-update. Run `brew upgrade claude-code` periodically to get the latest features and security fixes.77 Homebrew installations do not auto-update. Run `brew upgrade claude-code` or `brew upgrade claude-code@latest`, depending on which cask you installed, to get the latest features and security fixes.

58 </Info>78 </Info>

59 </Tab>79 </Tab>

60 80 


69 </Tab>89 </Tab>

70</Tabs>90</Tabs>

71 91 

72After the installation process completes, navigate to your project and start Claude Code:92You can also install with [apt, dnf, or apk](/en/setup#install-with-linux-package-managers) on Debian, Fedora, RHEL, and Alpine.

93 

94After installation completes, open a terminal in the project you want to work in and start Claude Code:

73 95 

74```bash theme={null}96```bash theme={null}

75cd your-awesome-project

76claude97claude

77```98```

78 99 

79If you encounter any issues during installation, consult the [troubleshooting guide](/en/troubleshooting).100If you encounter any issues during installation, see the [troubleshooting guide](/en/troubleshooting).

80 101 

81<Tip>102### Set up on Windows

82 Run `claude doctor` after installation to check your installation type and version.103 

83</Tip>104You can run Claude Code natively on Windows or inside WSL. Pick based on where your projects are located and which features you need:

105 

106| Option | Requires | [Sandboxing](/en/sandboxing) | When to use |

107| -------------- | ---------------------------------------------------- | ---------------------------- | ----------------------------------------------- |

108| Native Windows | [Git for Windows](https://git-scm.com/downloads/win) | Not supported | Windows-native projects and tools |

109| WSL 2 | WSL 2 enabled | Supported | Linux toolchains or sandboxed command execution |

110| WSL 1 | WSL 1 enabled | Not supported | If WSL 2 is unavailable |

111 

112**Option 1: Native Windows with Git Bash**

113 

114Install [Git for Windows](https://git-scm.com/downloads/win), then run the install command from PowerShell or CMD. You do not need to run as Administrator.

115 

116Whether you install from PowerShell or CMD only affects which install command you run. Your prompt shows `PS C:\Users\YourName>` in PowerShell and `C:\Users\YourName>` without the `PS` in CMD. If you're new to the terminal, the [terminal guide](/en/terminal-guide#windows) walks through each step.

117 

118After installation, launch `claude` from PowerShell, CMD, or Git Bash. Claude Code uses Git Bash internally to execute commands regardless of where you launched it. If Claude Code can't find your Git Bash installation, set the path in your [settings.json file](/en/settings):

119 

120```json theme={null}

121{

122 "env": {

123 "CLAUDE_CODE_GIT_BASH_PATH": "C:\\Program Files\\Git\\bin\\bash.exe"

124 }

125}

126```

127 

128Claude Code can also run PowerShell natively on Windows. The PowerShell tool is rolling out progressively; set `CLAUDE_CODE_USE_POWERSHELL_TOOL=1` to opt in or `0` to opt out. See [PowerShell tool](/en/tools-reference#powershell-tool) for setup and limitations.

129 

130**Option 2: WSL**

131 

132Open your WSL distribution and run the Linux installer from the [install instructions](#install-claude-code) above. You install and launch `claude` inside the WSL terminal, not from PowerShell or CMD.

133 

134### Alpine Linux and musl-based distributions

135 

136The native installer on Alpine and other musl/uClibc-based distributions requires `libgcc`, `libstdc++`, and `ripgrep`. Install these using your distribution's package manager, then set `USE_BUILTIN_RIPGREP=0`.

137 

138This example installs the required packages on Alpine:

139 

140```bash theme={null}

141apk add libgcc libstdc++ ripgrep

142```

143 

144Then set `USE_BUILTIN_RIPGREP` to `0` in your [`settings.json`](/en/settings#available-settings) file:

145 

146```json theme={null}

147{

148 "env": {

149 "USE_BUILTIN_RIPGREP": "0"

150 }

151}

152```

153 

154## Verify your installation

155 

156After installing, confirm Claude Code is working:

157 

158```bash theme={null}

159claude --version

160```

161 

162For a more detailed check of your installation and configuration, run [`claude doctor`](/en/troubleshooting#get-more-help):

163 

164```bash theme={null}

165claude doctor

166```

167 

168## Authenticate

169 

170Claude Code requires a Pro, Max, Team, Enterprise, or Console account. The free Claude.ai plan does not include Claude Code access. You can also use Claude Code with a third-party API provider like [Amazon Bedrock](/en/amazon-bedrock), [Google Vertex AI](/en/google-vertex-ai), or [Microsoft Foundry](/en/microsoft-foundry).

171 

172After installing, log in by running `claude` and following the browser prompts. See [Authentication](/en/authentication) for all account types and team setup options.

173 

174## Update Claude Code

175 

176Native installations automatically update in the background. You can [configure the release channel](#configure-release-channel) to control whether you receive updates immediately or on a delayed stable schedule, or [disable auto-updates](#disable-auto-updates) entirely. Homebrew, WinGet, and [Linux package manager](#install-with-linux-package-managers) installations require manual updates.

177 

178### Auto-updates

179 

180Claude Code checks for updates on startup and periodically while running. Updates download and install in the background, then take effect the next time you start Claude Code.

84 181 

85<Note>182<Note>

86 **Alpine Linux and other musl/uClibc-based distributions**: The native installer requires `libgcc`, `libstdc++`, and `ripgrep`. For Alpine: `apk add libgcc libstdc++ ripgrep`. Set `USE_BUILTIN_RIPGREP=0`.183 Homebrew, WinGet, apt, dnf, and apk installations do not auto-update. For Homebrew, run `brew upgrade claude-code` or `brew upgrade claude-code@latest`, depending on which cask you installed. For WinGet, run `winget upgrade Anthropic.ClaudeCode`. For Linux package managers, see the upgrade commands in [Install with Linux package managers](#install-with-linux-package-managers).

184 

185 **Known issue:** Claude Code may notify you of updates before the new version is available in these package managers. If an upgrade fails, wait and try again later.

186 

187 Homebrew keeps old versions on disk after upgrades. Run `brew cleanup` periodically to reclaim disk space.

87</Note>188</Note>

88 189 

89### Authentication190### Configure release channel

191 

192Control which release channel Claude Code follows for auto-updates and `claude update` with the `autoUpdatesChannel` setting:

193 

194* `"latest"`, the default: receive new features as soon as they're released

195* `"stable"`: use a version that is typically about one week old, skipping releases with major regressions

196 

197Configure this via `/config` → **Auto-update channel**, or add it to your [settings.json file](/en/settings):

198 

199```json theme={null}

200{

201 "autoUpdatesChannel": "stable"

202}

203```

204 

205For enterprise deployments, you can enforce a consistent release channel across your organization using [managed settings](/en/permissions#managed-settings).

206 

207Homebrew installations choose a channel by cask name instead of this setting: `claude-code` tracks stable and `claude-code@latest` tracks latest.

208 

209### Pin a minimum version

210 

211The `minimumVersion` setting establishes a floor. Background auto-updates and `claude update` refuse to install any version below this value, so moving to the `"stable"` channel does not downgrade you if you are already on a newer `"latest"` build.

212 

213Switching from `"latest"` to `"stable"` via `/config` prompts you to either stay on the current version or allow the downgrade. Choosing to stay sets `minimumVersion` to that version. Switching back to `"latest"` clears it.

214 

215Add it to your [settings.json file](/en/settings) to pin a floor explicitly:

216 

217```json theme={null}

218{

219 "autoUpdatesChannel": "stable",

220 "minimumVersion": "2.1.100"

221}

222```

223 

224In [managed settings](/en/permissions#managed-settings), this enforces an organization-wide minimum that user and project settings cannot override.

225 

226### Disable auto-updates

227 

228Set `DISABLE_AUTOUPDATER` to `"1"` in the `env` key of your [`settings.json`](/en/settings#available-settings) file:

229 

230```json theme={null}

231{

232 "env": {

233 "DISABLE_AUTOUPDATER": "1"

234 }

235}

236```

237 

238`DISABLE_AUTOUPDATER` only stops the background check; `claude update` and `claude install` still work. To block all update paths, including manual updates, set [`DISABLE_UPDATES`](/en/env-vars) instead. Use this when you distribute Claude Code through your own channels and need users to stay on the version you provide.

90 239 

91#### For individuals240### Update manually

92 241 

931. **Claude Pro or Max plan** (recommended): Subscribe to Claude's [Pro or Max plan](https://claude.ai/pricing) for a unified subscription that includes both Claude Code and Claude on the web. Manage your account in one place and log in with your Claude.ai account.242To apply an update immediately without waiting for the next background check, run:

942. **Claude Console**: Connect through the [Claude Console](https://console.anthropic.com) and complete the OAuth process. Requires active billing in the Anthropic Console. A "Claude Code" workspace is automatically created for usage tracking and cost management. You can't create API keys for the Claude Code workspace; it's dedicated exclusively for Claude Code usage.

95 243 

96#### For teams and organizations244```bash theme={null}

245claude update

246```

97 247 

981. **Claude for Teams or Enterprise** (recommended): Subscribe to [Claude for Teams](https://claude.com/pricing#team-&-enterprise) or [Claude for Enterprise](https://anthropic.com/contact-sales) for centralized billing, team management, and access to both Claude Code and Claude on the web. Team members log in with their Claude.ai accounts.248## Advanced installation options

992. **Claude Console with team billing**: Set up a shared [Claude Console](https://console.anthropic.com) organization with team billing. Invite team members and assign roles for usage tracking.249 

1003. **Cloud providers**: Configure Claude Code to use [Amazon Bedrock, Google Vertex AI, or Microsoft Foundry](/en/third-party-integrations) for deployments with your existing cloud infrastructure.250These options are for version pinning, Linux package managers, npm, and verifying binary integrity.

101 251 

102### Install a specific version252### Install a specific version

103 253 

104The native installer accepts either a specific version number or a release channel (`latest` or `stable`). The channel you choose at install time becomes your default for auto-updates. See [Configure release channel](#configure-release-channel) for more information.254The native installer accepts either a specific version number or a release channel (`latest` or `stable`). The channel you choose at install time becomes your default for auto-updates. See [configure release channel](#configure-release-channel) for more information.

105 255 

106To install the latest version (default):256To install the latest version (default):

107 257 


152<Tabs>302<Tabs>

153 <Tab title="macOS, Linux, WSL">303 <Tab title="macOS, Linux, WSL">

154 ```bash theme={null}304 ```bash theme={null}

155 curl -fsSL https://claude.ai/install.sh | bash -s 1.0.58305 curl -fsSL https://claude.ai/install.sh | bash -s 2.1.89

156 ```306 ```

157 </Tab>307 </Tab>

158 308 

159 <Tab title="Windows PowerShell">309 <Tab title="Windows PowerShell">

160 ```powershell theme={null}310 ```powershell theme={null}

161 & ([scriptblock]::Create((irm https://claude.ai/install.ps1))) 1.0.58311 & ([scriptblock]::Create((irm https://claude.ai/install.ps1))) 2.1.89

162 ```312 ```

163 </Tab>313 </Tab>

164 314 

165 <Tab title="Windows CMD">315 <Tab title="Windows CMD">

166 ```batch theme={null}316 ```batch theme={null}

167 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd 1.0.58 && del install.cmd317 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd 2.1.89 && del install.cmd

168 ```318 ```

169 </Tab>319 </Tab>

170</Tabs>320</Tabs>

171 321 

172### Binary integrity and code signing322### Install with Linux package managers

323 

324Claude Code publishes signed apt, dnf, and apk repositories. Replace `stable` with `latest` for the rolling channel. Package manager installations do not auto-update through Claude Code; updates arrive through your normal system upgrade workflow.

325 

326All repositories are signed with the [Claude Code release signing key](#binary-integrity-and-code-signing). Before trusting the key, verify it as described in each tab.

327 

328<Tabs>

329 <Tab title="apt">

330 For Debian and Ubuntu. To use the rolling channel, change both `stable` occurrences in the `deb` line: the URL path and the suite name.

331 

332 ```bash theme={null}

333 sudo install -d -m 0755 /etc/apt/keyrings

334 sudo curl -fsSL https://downloads.claude.ai/keys/claude-code.asc \

335 -o /etc/apt/keyrings/claude-code.asc

336 echo "deb [signed-by=/etc/apt/keyrings/claude-code.asc] https://downloads.claude.ai/claude-code/apt/stable stable main" \

337 | sudo tee /etc/apt/sources.list.d/claude-code.list

338 sudo apt update

339 sudo apt install claude-code

340 ```

341 

342 Verify the GPG key fingerprint before trusting it: `gpg --show-keys /etc/apt/keyrings/claude-code.asc` should report `31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE`.

343 

344 To upgrade later, run `sudo apt update && sudo apt upgrade claude-code`.

345 </Tab>

346 

347 <Tab title="dnf">

348 For Fedora and RHEL:

349 

350 ```bash theme={null}

351 sudo tee /etc/yum.repos.d/claude-code.repo <<'EOF'

352 [claude-code]

353 name=Claude Code

354 baseurl=https://downloads.claude.ai/claude-code/rpm/stable

355 enabled=1

356 gpgcheck=1

357 gpgkey=https://downloads.claude.ai/keys/claude-code.asc

358 EOF

359 sudo dnf install claude-code

360 ```

361 

362 dnf downloads the key on first install and prompts you to confirm the fingerprint. Verify it matches `31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE` before accepting.

173 363 

174* SHA256 checksums for all platforms are published in the release manifests, currently located at `https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/{VERSION}/manifest.json` (example: replace `{VERSION}` with `2.0.30`)364 To upgrade later, run `sudo dnf upgrade claude-code`.

175* Signed binaries are distributed for the following platforms:365 </Tab>

176 * macOS: Signed by "Anthropic PBC" and notarized by Apple366 

177 * Windows: Signed by "Anthropic, PBC"367 <Tab title="apk">

368 For Alpine Linux:

178 369 

179## NPM installation (deprecated)370 ```sh theme={null}

371 wget -O /etc/apk/keys/claude-code.rsa.pub \

372 https://downloads.claude.ai/keys/claude-code.rsa.pub

373 echo "https://downloads.claude.ai/claude-code/apk/stable" >> /etc/apk/repositories

374 apk add claude-code

375 ```

376 

377 Verify the downloaded key with `sha256sum /etc/apk/keys/claude-code.rsa.pub`, which should report `395759c1f7449ef4cdef305a42e820f3c766d6090d142634ebdb049f113168b6`.

378 

379 To upgrade later, run `apk update && apk upgrade claude-code`.

380 </Tab>

381</Tabs>

180 382 

181NPM installation is deprecated. Use the [native installation](#installation) method when possible. To migrate an existing npm installation to native, run `claude install`.383### Install with npm

182 384 

183**Global npm installation**385You can also install Claude Code as a global npm package. The package requires [Node.js 18 or later](https://nodejs.org/en/download).

184 386 

185```sh theme={null}387```bash theme={null}

186npm install -g @anthropic-ai/claude-code388npm install -g @anthropic-ai/claude-code

187```389```

188 390 

391The npm package installs the same native binary as the standalone installer. npm pulls the binary in through a per-platform optional dependency such as `@anthropic-ai/claude-code-darwin-arm64`, and a postinstall step links it into place. The installed `claude` binary does not itself invoke Node.

392 

393Supported npm install platforms are `darwin-arm64`, `darwin-x64`, `linux-x64`, `linux-arm64`, `linux-x64-musl`, `linux-arm64-musl`, `win32-x64`, and `win32-arm64`. Your package manager must allow optional dependencies. See [troubleshooting](/en/troubleshooting#native-binary-not-found-after-npm-install) if the binary is missing after install.

394 

189<Warning>395<Warning>

190 Do NOT use `sudo npm install -g` as this can lead to permission issues and security risks.396 Do NOT use `sudo npm install -g` as this can lead to permission issues and security risks. If you encounter permission errors, see [troubleshooting permission errors](/en/troubleshooting#permission-errors-during-installation).

191 If you encounter permission errors, see [troubleshooting permission errors](/en/troubleshooting#command-not-found-claude-or-permission-errors) for recommended solutions.

192</Warning>397</Warning>

193 398 

194## Windows setup399### Binary integrity and code signing

195 400 

196**Option 1: Claude Code within WSL**401Each release publishes a `manifest.json` containing SHA256 checksums for every platform binary. The manifest is signed with an Anthropic GPG key, so verifying the signature on the manifest transitively verifies every binary it lists.

197 402 

198* Both WSL 1 and WSL 2 are supported403#### Verify the manifest signature

199* WSL 2 supports [sandboxing](/en/sandboxing) for enhanced security. WSL 1 does not support sandboxing.

200 404 

201**Option 2: Claude Code on native Windows with Git Bash**405Steps 1-3 require a POSIX shell with `gpg` and `curl`. On Windows, run them in Git Bash or WSL. Step 4 includes a PowerShell option.

202 406 

203* Requires [Git for Windows](https://git-scm.com/downloads/win)407<Steps>

204* For portable Git installations, specify the path to your `bash.exe`:408 <Step title="Download and import the public key">

205 ```powershell theme={null}409 The release signing key is published at a fixed URL.

206 $env:CLAUDE_CODE_GIT_BASH_PATH="C:\Program Files\Git\bin\bash.exe"410 

411 ```bash theme={null}

412 curl -fsSL https://downloads.claude.ai/keys/claude-code.asc | gpg --import

207 ```413 ```

208 414 

209## Update Claude Code415 Display the fingerprint of the imported key.

210 416 

211### Auto updates417 ```bash theme={null}

418 gpg --fingerprint security@anthropic.com

419 ```

212 420 

213Claude Code automatically keeps itself up to date to ensure you have the latest features and security fixes.421 Confirm the output includes this fingerprint:

214 422 

215* **Update checks**: Performed on startup and periodically while running423 ```text theme={null}

216* **Update process**: Downloads and installs automatically in the background424 31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE

217* **Notifications**: You'll see a notification when updates are installed425 ```

218* **Applying updates**: Updates take effect the next time you start Claude Code426 </Step>

219 427 

220<Note>428 <Step title="Download the manifest and signature">

221 Homebrew and WinGet installations do not auto-update. Use `brew upgrade claude-code` or `winget upgrade Anthropic.ClaudeCode` to update manually.429 Set `VERSION` to the release you want to verify.

222 430 

223 **Known issue:** Claude Code may notify you of updates before the new version is available in these package managers. If an upgrade fails, wait and try again later.431 ```bash theme={null}

224</Note>432 REPO=https://downloads.claude.ai/claude-code-releases

433 VERSION=2.1.89

434 curl -fsSLO "$REPO/$VERSION/manifest.json"

435 curl -fsSLO "$REPO/$VERSION/manifest.json.sig"

436 ```

437 </Step>

225 438 

226### Configure release channel439 <Step title="Verify the signature">

440 Verify the detached signature against the manifest.

227 441 

228Configure which release channel Claude Code follows for both auto-updates and `claude update` with the `autoUpdatesChannel` setting:442 ```bash theme={null}

443 gpg --verify manifest.json.sig manifest.json

444 ```

229 445 

230* `"latest"` (default): Receive new features as soon as they're released446 A valid result reports `Good signature from "Anthropic Claude Code Release Signing <security@anthropic.com>"`.

231* `"stable"`: Use a version that is typically about one week old, skipping releases with major regressions

232 447 

233Configure this via `/config` **Auto-update channel**, or add it to your [settings.json file](/en/settings):448 `gpg` also prints `WARNING: This key is not certified with a trusted signature!` for any freshly imported key. This is expected. The `Good signature` line confirms the cryptographic check passed. The fingerprint comparison in Step 1 confirms the key itself is authentic.

449 </Step>

234 450 

235```json theme={null}451 <Step title="Check the binary against the manifest">

236{452 Compare the SHA256 checksum of your downloaded binary with the value listed under `platforms.<platform>.checksum` in `manifest.json`.

237 "autoUpdatesChannel": "stable"453 

238}454 <Tabs>

239```455 <Tab title="Linux">

456 ```bash theme={null}

457 sha256sum claude

458 ```

459 </Tab>

240 460 

241For enterprise deployments, you can enforce a consistent release channel across your organization using [managed settings](/en/iam#managed-settings).461 <Tab title="macOS">

462 ```bash theme={null}

463 shasum -a 256 claude

464 ```

465 </Tab>

242 466 

243### Disable auto-updates467 <Tab title="Windows PowerShell">

468 ```powershell theme={null}

469 (Get-FileHash claude.exe -Algorithm SHA256).Hash.ToLower()

470 ```

471 </Tab>

472 </Tabs>

473 </Step>

474</Steps>

244 475 

245Set the `DISABLE_AUTOUPDATER` environment variable in your shell or [settings.json file](/en/settings):476<Note>

477 Manifest signatures are available for releases from `2.1.89` onward. Earlier releases publish checksums in `manifest.json` without a detached signature.

478</Note>

246 479 

247```bash theme={null}480#### Platform code signatures

248export DISABLE_AUTOUPDATER=1

249```

250 481 

251### Update manually482In addition to the signed manifest, individual binaries carry platform-native code signatures where supported.

252 483 

253```bash theme={null}484* **macOS**: signed by "Anthropic PBC" and notarized by Apple. Verify with `codesign --verify --verbose ./claude`.

254claude update485* **Windows**: signed by "Anthropic, PBC". Verify with `Get-AuthenticodeSignature .\claude.exe`.

255```486* **Linux**: binaries are not individually code-signed. If you download directly from the `claude-code-releases` bucket or use the native installer, verify integrity with the manifest signature above. If you install with [apt, dnf, or apk](#install-with-linux-package-managers), your package manager verifies signatures automatically using the repository signing key.

256 487 

257## Uninstall Claude Code488## Uninstall Claude Code

258 489 

259If you need to uninstall Claude Code, follow the instructions for your installation method.490To remove Claude Code, follow the instructions for your installation method.

260 491 

261### Native installation492### Native installation

262 493 

263Remove the Claude Code binary and version files:494Remove the Claude Code binary and version files:

264 495 

265**macOS, Linux, WSL:**496<Tabs>

266 497 <Tab title="macOS, Linux, WSL">

267```bash theme={null}498 ```bash theme={null}

268rm -f ~/.local/bin/claude499 rm -f ~/.local/bin/claude

269rm -rf ~/.local/share/claude500 rm -rf ~/.local/share/claude

270```501 ```

502 </Tab>

271 503 

272**Windows PowerShell:**504 <Tab title="Windows PowerShell">

505 ```powershell theme={null}

506 Remove-Item -Path "$env:USERPROFILE\.local\bin\claude.exe" -Force

507 Remove-Item -Path "$env:USERPROFILE\.local\share\claude" -Recurse -Force

508 ```

509 </Tab>

510</Tabs>

273 511 

274```powershell theme={null}512### Homebrew installation

275Remove-Item -Path "$env:USERPROFILE\.local\bin\claude.exe" -Force

276Remove-Item -Path "$env:USERPROFILE\.local\share\claude" -Recurse -Force

277```

278 513 

279**Windows CMD:**514Remove the Homebrew cask you installed. If you installed the stable cask:

280 515 

281```batch theme={null}516```bash theme={null}

282del "%USERPROFILE%\.local\bin\claude.exe"517brew uninstall --cask claude-code

283rmdir /s /q "%USERPROFILE%\.local\share\claude"

284```518```

285 519 

286### Homebrew installation520If you installed the latest cask:

287 521 

288```bash theme={null}522```bash theme={null}

289brew uninstall --cask claude-code523brew uninstall --cask claude-code@latest

290```524```

291 525 

292### WinGet installation526### WinGet installation

293 527 

528Remove the WinGet package:

529 

294```powershell theme={null}530```powershell theme={null}

295winget uninstall Anthropic.ClaudeCode531winget uninstall Anthropic.ClaudeCode

296```532```

297 533 

298### NPM installation534### apt / dnf / apk

535 

536Remove the package and the repository configuration:

537 

538<Tabs>

539 <Tab title="apt">

540 ```bash theme={null}

541 sudo apt remove claude-code

542 sudo rm /etc/apt/sources.list.d/claude-code.list /etc/apt/keyrings/claude-code.asc

543 ```

544 </Tab>

545 

546 <Tab title="dnf">

547 ```bash theme={null}

548 sudo dnf remove claude-code

549 sudo rm /etc/yum.repos.d/claude-code.repo

550 ```

551 </Tab>

552 

553 <Tab title="apk">

554 ```sh theme={null}

555 apk del claude-code

556 sed -i '\|downloads.claude.ai/claude-code/apk|d' /etc/apk/repositories

557 rm /etc/apk/keys/claude-code.rsa.pub

558 ```

559 </Tab>

560</Tabs>

561 

562### npm

563 

564Remove the global npm package:

299 565 

300```bash theme={null}566```bash theme={null}

301npm uninstall -g @anthropic-ai/claude-code567npm uninstall -g @anthropic-ai/claude-code

302```568```

303 569 

304### Clean up configuration files (optional)570### Remove configuration files

305 571 

306<Warning>572<Warning>

307 Removing configuration files will delete all your settings, allowed tools, MCP server configurations, and session history.573 Removing configuration files will delete all your settings, allowed tools, MCP server configurations, and session history.

308</Warning>574</Warning>

309 575 

310To remove Claude Code settings and cached data:576The VS Code extension, the JetBrains plugin, and the Desktop app also write to `~/.claude/`. If any of them is still installed, the directory is recreated the next time it runs. To remove Claude Code completely, uninstall the [VS Code extension](/en/vs-code#uninstall-the-extension), the JetBrains plugin, and the Desktop app before deleting these files.

311 

312**macOS, Linux, WSL:**

313 

314```bash theme={null}

315# Remove user settings and state

316rm -rf ~/.claude

317rm ~/.claude.json

318 

319# Remove project-specific settings (run from your project directory)

320rm -rf .claude

321rm -f .mcp.json

322```

323 

324**Windows PowerShell:**

325 577 

326```powershell theme={null}578To remove Claude Code settings and cached data:

327# Remove user settings and state

328Remove-Item -Path "$env:USERPROFILE\.claude" -Recurse -Force

329Remove-Item -Path "$env:USERPROFILE\.claude.json" -Force

330 579 

331# Remove project-specific settings (run from your project directory)580<Tabs>

332Remove-Item -Path ".claude" -Recurse -Force581 <Tab title="macOS, Linux, WSL">

333Remove-Item -Path ".mcp.json" -Force582 ```bash theme={null}

334```583 # Remove user settings and state

584 rm -rf ~/.claude

585 rm ~/.claude.json

335 586 

336**Windows CMD:**587 # Remove project-specific settings (run from your project directory)

588 rm -rf .claude

589 rm -f .mcp.json

590 ```

591 </Tab>

337 592 

338```batch theme={null}593 <Tab title="Windows PowerShell">

339REM Remove user settings and state594 ```powershell theme={null}

340rmdir /s /q "%USERPROFILE%\.claude"595 # Remove user settings and state

341del "%USERPROFILE%\.claude.json"596 Remove-Item -Path "$env:USERPROFILE\.claude" -Recurse -Force

597 Remove-Item -Path "$env:USERPROFILE\.claude.json" -Force

342 598 

343REM Remove project-specific settings (run from your project directory)599 # Remove project-specific settings (run from your project directory)

344rmdir /s /q ".claude"600 Remove-Item -Path ".claude" -Recurse -Force

345del ".mcp.json"601 Remove-Item -Path ".mcp.json" -Force

346```602 ```

603 </Tab>

604</Tabs>

skills.md +93 −35

Details

4 4 

5# Extend Claude with skills5# Extend Claude with skills

6 6 

7> Create, manage, and share skills to extend Claude's capabilities in Claude Code. Includes custom slash commands.7> Create, manage, and share skills to extend Claude's capabilities in Claude Code. Includes custom commands and bundled skills.

8 8 

9Skills extend what Claude can do. Create a `SKILL.md` file with instructions, and Claude adds it to its toolkit. Claude uses skills when relevant, or you can invoke one directly with `/skill-name`.9Skills extend what Claude can do. Create a `SKILL.md` file with instructions, and Claude adds it to its toolkit. Claude uses skills when relevant, or you can invoke one directly with `/skill-name`.

10 10 

11Create a skill when you keep pasting the same playbook, checklist, or multi-step procedure into chat, or when a section of CLAUDE.md has grown into a procedure rather than a fact. Unlike CLAUDE.md content, a skill's body loads only when it's used, so long reference material costs almost nothing until you need it.

12 

11<Note>13<Note>

12 For built-in commands like `/help` and `/compact`, see [interactive mode](/en/interactive-mode#built-in-commands).14 For built-in commands like `/help` and `/compact`, and bundled skills like `/debug` and `/simplify`, see the [commands reference](/en/commands).

13 15 

14 **Custom slash commands have been merged into skills.** A file at `.claude/commands/review.md` and a skill at `.claude/skills/review/SKILL.md` both create `/review` and work the same way. Your existing `.claude/commands/` files keep working. Skills add optional features: a directory for supporting files, frontmatter to [control whether you or Claude invokes them](#control-who-invokes-a-skill), and the ability for Claude to load them automatically when relevant.16 **Custom commands have been merged into skills.** A file at `.claude/commands/deploy.md` and a skill at `.claude/skills/deploy/SKILL.md` both create `/deploy` and work the same way. Your existing `.claude/commands/` files keep working. Skills add optional features: a directory for supporting files, frontmatter to [control whether you or Claude invokes them](#control-who-invokes-a-skill), and the ability for Claude to load them automatically when relevant.

15</Note>17</Note>

16 18 

17Claude Code skills follow the [Agent Skills](https://agentskills.io) open standard, which works across multiple AI tools. Claude Code extends the standard with additional features like [invocation control](#control-who-invokes-a-skill), [subagent execution](#run-skills-in-a-subagent), and [dynamic context injection](#inject-dynamic-context).19Claude Code skills follow the [Agent Skills](https://agentskills.io) open standard, which works across multiple AI tools. Claude Code extends the standard with additional features like [invocation control](#control-who-invokes-a-skill), [subagent execution](#run-skills-in-a-subagent), and [dynamic context injection](#inject-dynamic-context).

18 20 

21## Bundled skills

22 

23Claude Code includes a set of bundled skills that are available in every session, including `/simplify`, `/batch`, `/debug`, `/loop`, and `/claude-api`. Unlike most built-in commands, which execute fixed logic directly, bundled skills are prompt-based: they give Claude a detailed playbook and let it orchestrate the work using its tools. You invoke them the same way as any other skill, by typing `/` followed by the skill name.

24 

25Bundled skills are listed alongside built-in commands in the [commands reference](/en/commands), marked **Skill** in the Purpose column.

26 

19## Getting started27## Getting started

20 28 

21### Create your first skill29### Create your first skill


58 66 

59 **Let Claude invoke it automatically** by asking something that matches the description:67 **Let Claude invoke it automatically** by asking something that matches the description:

60 68 

61 ```69 ```text theme={null}

62 How does this code work?70 How does this code work?

63 ```71 ```

64 72 

65 **Or invoke it directly** with the skill name:73 **Or invoke it directly** with the skill name:

66 74 

67 ```75 ```text theme={null}

68 /explain-code src/auth/login.ts76 /explain-code src/auth/login.ts

69 ```77 ```

70 78 


77Where you store a skill determines who can use it:85Where you store a skill determines who can use it:

78 86 

79| Location | Path | Applies to |87| Location | Path | Applies to |

80| :--------- | :----------------------------------------------- | :----------------------------- |88| :--------- | :-------------------------------------------------- | :----------------------------- |

81| Enterprise | See [managed settings](/en/iam#managed-settings) | All users in your organization |89| Enterprise | See [managed settings](/en/settings#settings-files) | All users in your organization |

82| Personal | `~/.claude/skills/<skill-name>/SKILL.md` | All your projects |90| Personal | `~/.claude/skills/<skill-name>/SKILL.md` | All your projects |

83| Project | `.claude/skills/<skill-name>/SKILL.md` | This project only |91| Project | `.claude/skills/<skill-name>/SKILL.md` | This project only |

84| Plugin | `<plugin>/skills/<skill-name>/SKILL.md` | Where plugin is enabled |92| Plugin | `<plugin>/skills/<skill-name>/SKILL.md` | Where plugin is enabled |

85 93 

86When skills share the same name across levels, higher-priority locations win: enterprise > personal > project. Plugin skills use a `plugin-name:skill-name` namespace, so they cannot conflict with other levels. If you have files in `.claude/commands/`, those work the same way, but if a skill and a command share the same name, the skill takes precedence.94When skills share the same name across levels, enterprise overrides personal, and personal overrides project. Plugin skills use a `plugin-name:skill-name` namespace, so they cannot conflict with other levels. If you have files in `.claude/commands/`, those work the same way, but if a skill and a command share the same name, the skill takes precedence.

95 

96#### Live change detection

97 

98Claude Code watches skill directories for file changes. Adding, editing, or removing a skill under `~/.claude/skills/`, the project `.claude/skills/`, or a `.claude/skills/` inside an `--add-dir` directory takes effect within the current session without restarting. Creating a top-level skills directory that did not exist when the session started requires restarting Claude Code so the new directory can be watched.

87 99 

88#### Automatic discovery from nested directories100#### Automatic discovery from nested directories

89 101 


91 103 

92Each skill is a directory with `SKILL.md` as the entrypoint:104Each skill is a directory with `SKILL.md` as the entrypoint:

93 105 

94```106```text theme={null}

95my-skill/107my-skill/

96├── SKILL.md # Main instructions (required)108├── SKILL.md # Main instructions (required)

97├── template.md # Template for Claude to fill in109├── template.md # Template for Claude to fill in


107 Files in `.claude/commands/` still work and support the same [frontmatter](#frontmatter-reference). Skills are recommended since they support additional features like supporting files.119 Files in `.claude/commands/` still work and support the same [frontmatter](#frontmatter-reference). Skills are recommended since they support additional features like supporting files.

108</Note>120</Note>

109 121 

122#### Skills from additional directories

123 

124The `--add-dir` flag [grants file access](/en/permissions#additional-directories-grant-file-access-not-configuration) rather than configuration discovery, but skills are an exception: `.claude/skills/` within an added directory is loaded automatically. See [Live change detection](#live-change-detection) for how edits are picked up during a session.

125 

126Other `.claude/` configuration such as subagents, commands, and output styles is not loaded from additional directories. See the [exceptions table](/en/permissions#additional-directories-grant-file-access-not-configuration) for the complete list of what is and isn't loaded, and the recommended ways to share configuration across projects.

127 

128<Note>

129 CLAUDE.md files from `--add-dir` directories are not loaded by default. To load them, set `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1`. See [Load from additional directories](/en/memory#load-from-additional-directories).

130</Note>

131 

110## Configure skills132## Configure skills

111 133 

112Skills are configured through YAML frontmatter at the top of `SKILL.md` and the markdown content that follows.134Skills are configured through YAML frontmatter at the top of `SKILL.md` and the markdown content that follows.


156name: my-skill178name: my-skill

157description: What this skill does179description: What this skill does

158disable-model-invocation: true180disable-model-invocation: true

159allowed-tools: Read, Grep181allowed-tools: Read Grep

160---182---

161 183 

162Your skill instructions here...184Your skill instructions here...


165All 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.

166 188 

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

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

169| `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). |

170| `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. Front-load the key use case: the combined `description` and `when_to_use` text is truncated at 1,536 characters in the skill listing to reduce context usage. |

193| `when_to_use` | No | Additional context for when Claude should invoke the skill, such as trigger phrases or example requests. Appended to `description` in the skill listing and counts toward the 1,536-character cap. |

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

172| `disable-model-invocation` | No | Set to `true` to prevent Claude from automatically loading this skill. Use for workflows you want to trigger manually with `/name`. Default: `false`. |195| `arguments` | No | Named positional arguments for [`$name` substitution](#available-string-substitutions) in the skill content. Accepts a space-separated string or a YAML list. Names map to argument positions in order. |

196| `disable-model-invocation` | No | Set to `true` to prevent Claude from automatically loading this skill. Use for workflows you want to trigger manually with `/name`. Also prevents the skill from being [preloaded into subagents](/en/sub-agents#preload-skills-into-subagents). Default: `false`. |

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

174| `allowed-tools` | No | Tools Claude can use without asking permission when this skill is active. |198| `allowed-tools` | No | Tools Claude can use without asking permission when this skill is active. Accepts a space-separated string or a YAML list. |

175| `model` | No | Model to use when this skill is active. |199| `model` | No | Model to use when this skill is active. The override applies for the rest of the current turn and is not saved to settings; the session model resumes on your next prompt. Accepts the same values as [`/model`](/en/model-config), or `inherit` to keep the active model. |

200| `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`, `xhigh`, `max`; available levels depend on the model. |

176| `context` | No | Set to `fork` to run in a forked subagent context. |201| `context` | No | Set to `fork` to run in a forked subagent context. |

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

178| `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. |203| `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. |

204| `paths` | No | Glob patterns that limit when this skill is activated. Accepts a comma-separated string or a YAML list. When set, Claude loads the skill automatically only when working with files matching the patterns. Uses the same format as [path-specific rules](/en/memory#path-specific-rules). |

205| `shell` | No | Shell to use for `` !`command` `` and ` ```! ` blocks in this skill. Accepts `bash` (default) or `powershell`. Setting `powershell` runs inline shell commands via PowerShell on Windows. Requires `CLAUDE_CODE_USE_POWERSHELL_TOOL=1`. |

179 206 

180#### Available string substitutions207#### Available string substitutions

181 208 

182Skills support string substitution for dynamic values in the skill content:209Skills support string substitution for dynamic values in the skill content:

183 210 

184| Variable | Description |211| Variable | Description |

185| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |212| :--------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

186| `$ARGUMENTS` | All arguments passed when invoking the skill. If `$ARGUMENTS` is not present in the content, arguments are appended as `ARGUMENTS: <value>`. |213| `$ARGUMENTS` | All arguments passed when invoking the skill. If `$ARGUMENTS` is not present in the content, arguments are appended as `ARGUMENTS: <value>`. |

187| `$ARGUMENTS[N]` | Access a specific argument by 0-based index, such as `$ARGUMENTS[0]` for the first argument. |214| `$ARGUMENTS[N]` | Access a specific argument by 0-based index, such as `$ARGUMENTS[0]` for the first argument. |

188| `$N` | Shorthand for `$ARGUMENTS[N]`, such as `$0` for the first argument or `$1` for the second. |215| `$N` | Shorthand for `$ARGUMENTS[N]`, such as `$0` for the first argument or `$1` for the second. |

216| `$name` | Named argument declared in the [`arguments`](#frontmatter-reference) frontmatter list. Names map to positions in order, so with `arguments: [issue, branch]` the placeholder `$issue` expands to the first argument and `$branch` to the second. |

189| `${CLAUDE_SESSION_ID}` | The current session ID. Useful for logging, creating session-specific files, or correlating skill output with sessions. |217| `${CLAUDE_SESSION_ID}` | The current session ID. Useful for logging, creating session-specific files, or correlating skill output with sessions. |

218| `${CLAUDE_SKILL_DIR}` | The directory containing the skill's `SKILL.md` file. For plugin skills, this is the skill's subdirectory within the plugin, not the plugin root. Use this in bash injection commands to reference scripts or files bundled with the skill, regardless of the current working directory. |

219 

220Indexed arguments use shell-style quoting, so wrap multi-word values in quotes to pass them as a single argument. For example, `/my-skill "hello world" second` makes `$0` expand to `hello world` and `$1` to `second`. The `$ARGUMENTS` placeholder always expands to the full argument string as typed.

190 221 

191**Example using substitutions:**222**Example using substitutions:**

192 223 


205 236 

206Skills can include multiple files in their directory. This keeps `SKILL.md` focused on the essentials while letting Claude access detailed reference material only when needed. Large reference docs, API specifications, or example collections don't need to load into context every time the skill runs.237Skills can include multiple files in their directory. This keeps `SKILL.md` focused on the essentials while letting Claude access detailed reference material only when needed. Large reference docs, API specifications, or example collections don't need to load into context every time the skill runs.

207 238 

208```239```text theme={null}

209my-skill/240my-skill/

210├── SKILL.md (required - overview and navigation)241├── SKILL.md (required - overview and navigation)

211├── reference.md (detailed API docs - loaded when needed)242├── reference.md (detailed API docs - loaded when needed)


262 In a regular session, skill descriptions are loaded into context so Claude knows what's available, but full skill content only loads when invoked. [Subagents with preloaded skills](/en/sub-agents#preload-skills-into-subagents) work differently: the full skill content is injected at startup.293 In a regular session, skill descriptions are loaded into context so Claude knows what's available, but full skill content only loads when invoked. [Subagents with preloaded skills](/en/sub-agents#preload-skills-into-subagents) work differently: the full skill content is injected at startup.

263</Note>294</Note>

264 295 

265### Restrict tool access296### Skill content lifecycle

297 

298When you or Claude invoke a skill, the rendered `SKILL.md` content enters the conversation as a single message and stays there for the rest of the session. Claude Code does not re-read the skill file on later turns, so write guidance that should apply throughout a task as standing instructions rather than one-time steps.

299 

300[Auto-compaction](/en/how-claude-code-works#when-context-fills-up) carries invoked skills forward within a token budget. When the conversation is summarized to free context, Claude Code re-attaches the most recent invocation of each skill after the summary, keeping the first 5,000 tokens of each. Re-attached skills share a combined budget of 25,000 tokens. Claude Code fills this budget starting from the most recently invoked skill, so older skills can be dropped entirely after compaction if you have invoked many in one session.

301 

302If a skill seems to stop influencing behavior after the first response, the content is usually still present and the model is choosing other tools or approaches. Strengthen the skill's `description` and instructions so the model keeps preferring it, or use [hooks](/en/hooks) to enforce behavior deterministically. If the skill is large or you invoked several others after it, re-invoke it after compaction to restore the full content.

266 303 

267Use the `allowed-tools` field to limit which tools Claude can use when a skill is active. This skill creates a read-only mode where Claude can explore files but not modify them:304### Pre-approve tools for a skill

305 

306The `allowed-tools` field grants permission for the listed tools while the skill is active, so Claude can use them without prompting you for approval. It does not restrict which tools are available: every tool remains callable, and your [permission settings](/en/permissions) still govern tools that are not listed.

307 

308This skill lets Claude run git commands without per-use approval whenever you invoke it:

268 309 

269```yaml theme={null}310```yaml theme={null}

270---311---

271name: safe-reader312name: commit

272description: Read files without making changes313description: Stage and commit the current changes

273allowed-tools: Read, Grep, Glob314disable-model-invocation: true

315allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)

274---316---

275```317```

276 318 

319To block a skill from using certain tools, add deny rules in your [permission settings](/en/permissions) instead.

320 

277### Pass arguments to skills321### Pass arguments to skills

278 322 

279Both you and Claude can pass arguments when invoking a skill. Arguments are available via the `$ARGUMENTS` placeholder.323Both you and Claude can pass arguments when invoking a skill. Arguments are available via the `$ARGUMENTS` placeholder.


328 372 

329### Inject dynamic context373### Inject dynamic context

330 374 

331The `!`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.375The `` !`<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.

332 376 

333This 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:377This 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:

334 378 

335```yaml theme={null}379```yaml theme={null}

336---380---


352 396 

353When this skill runs:397When this skill runs:

354 398 

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

3562. The output replaces the placeholder in the skill content4002. The output replaces the placeholder in the skill content

3573. Claude receives the fully-rendered prompt with actual PR data4013. Claude receives the fully-rendered prompt with actual PR data

358 402 

359This is preprocessing, not something Claude executes. Claude only sees the final result.403This is preprocessing, not something Claude executes. Claude only sees the final result.

360 404 

405For multi-line commands, use a fenced code block opened with ` ```! ` instead of the inline form:

406 

407````markdown theme={null}

408## Environment

409```!

410node --version

411npm --version

412git status --short

413```

414````

415 

416To disable this behavior for skills and custom commands from user, project, plugin, or [additional-directory](#skills-from-additional-directories) sources, set `"disableSkillShellExecution": true` in [settings](/en/settings). Each command is replaced with `[shell command execution disabled by policy]` instead of being run. Bundled and managed skills are not affected. This setting is most useful in [managed settings](/en/permissions#managed-settings), where users cannot override it.

417 

361<Tip>418<Tip>

362 To enable [extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) in a skill, include the word "ultrathink" anywhere in your skill content.419 To enable [extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) in a skill, include the word "ultrathink" anywhere in your skill content.

363</Tip>420</Tip>


409 466 

410### Restrict Claude's skill access467### Restrict Claude's skill access

411 468 

412By default, Claude can invoke any skill that doesn't have `disable-model-invocation: true` set. Skills that define `allowed-tools` grant Claude access to those tools without per-use approval when the skill is active. Your [permission settings](/en/iam) still govern baseline approval behavior for all other tools. Built-in commands like `/compact` and `/init` are not available through the Skill tool.469By default, Claude can invoke any skill that doesn't have `disable-model-invocation: true` set. Skills that define `allowed-tools` grant Claude access to those tools without per-use approval when the skill is active. Your [permission settings](/en/permissions) still govern baseline approval behavior for all other tools. A few built-in commands are also available through the Skill tool, including `/init`, `/review`, and `/security-review`. Other built-in commands such as `/compact` are not.

413 470 

414Three ways to control which skills Claude can invoke:471Three ways to control which skills Claude can invoke:

415 472 

416**Disable all skills** by denying the Skill tool in `/permissions`:473**Disable all skills** by denying the Skill tool in `/permissions`:

417 474 

418```475```text theme={null}

419# Add to deny rules:476# Add to deny rules:

420Skill477Skill

421```478```

422 479 

423**Allow or deny specific skills** using [permission rules](/en/iam):480**Allow or deny specific skills** using [permission rules](/en/permissions):

424 481 

425```482```text theme={null}

426# Allow only specific skills483# Allow only specific skills

427Skill(commit)484Skill(commit)

428Skill(review-pr *)485Skill(review-pr *)


445 502 

446* **Project skills**: Commit `.claude/skills/` to version control503* **Project skills**: Commit `.claude/skills/` to version control

447* **Plugins**: Create a `skills/` directory in your [plugin](/en/plugins)504* **Plugins**: Create a `skills/` directory in your [plugin](/en/plugins)

448* **Managed**: Deploy organization-wide through [managed settings](/en/iam#managed-settings)505* **Managed**: Deploy organization-wide through [managed settings](/en/settings#settings-files)

449 506 

450### Generate visual output507### Generate visual output

451 508 


6541. Make the description more specific7111. Make the description more specific

6552. Add `disable-model-invocation: true` if you only want manual invocation7122. Add `disable-model-invocation: true` if you only want manual invocation

656 713 

657### Claude doesn't see all my skills714### Skill descriptions are cut short

658 715 

659Skill descriptions are loaded into context so Claude knows what's available. If you have many skills, they may exceed the character budget (default 15,000 characters). Run `/context` to check for a warning about excluded skills.716Skill descriptions are loaded into context so Claude knows what's available. All skill names are always included, but if you have many skills, descriptions are shortened to fit the character budget, which can strip the keywords Claude needs to match your request. The budget scales dynamically at 1% of the context window, with a fallback of 8,000 characters.

660 717 

661To increase the limit, set the `SLASH_COMMAND_TOOL_CHAR_BUDGET` environment variable.718To raise the limit, set the `SLASH_COMMAND_TOOL_CHAR_BUDGET` environment variable. Or trim the `description` and `when_to_use` text at the source: front-load the key use case, since each entry's combined text is capped at 1,536 characters regardless of budget.

662 719 

663## Related resources720## Related resources

664 721 

722* **[Debug your configuration](/en/debug-your-config)**: diagnose why a skill isn't appearing or triggering

665* **[Subagents](/en/sub-agents)**: delegate tasks to specialized agents723* **[Subagents](/en/sub-agents)**: delegate tasks to specialized agents

666* **[Plugins](/en/plugins)**: package and distribute skills with other extensions724* **[Plugins](/en/plugins)**: package and distribute skills with other extensions

667* **[Hooks](/en/hooks)**: automate workflows around tool events725* **[Hooks](/en/hooks)**: automate workflows around tool events

668* **[Memory](/en/memory)**: manage CLAUDE.md files for persistent context726* **[Memory](/en/memory)**: manage CLAUDE.md files for persistent context

669* **[Interactive mode](/en/interactive-mode#built-in-commands)**: built-in commands and shortcuts727* **[Commands](/en/commands)**: reference for built-in commands and bundled skills

670* **[Permissions](/en/iam)**: control tool and skill access728* **[Permissions](/en/permissions)**: control tool and skill access

slack.md +29 −4

Details

22Before using Claude Code in Slack, ensure you have the following:22Before using Claude Code in Slack, ensure you have the following:

23 23 

24| Requirement | Details |24| Requirement | Details |

25| :--------------------- | :----------------------------------------------------------------------------- |25| :--------------------- | :------------------------------------------------------------------------------------------------ |

26| Claude Plan | Pro, Max, Team, or Enterprise with Claude Code access (premium seats) |26| Claude Plan | Pro, Max, Team, or Enterprise with Claude Code access (premium seats or Chat + Claude Code seats) |

27| Claude Code on the web | Access to [Claude Code on the web](/en/claude-code-on-the-web) must be enabled |27| Claude Code on the web | Access to [Claude Code on the web](/en/claude-code-on-the-web) must be enabled |

28| GitHub Account | Connected to Claude Code on the web with at least one repository authenticated |28| GitHub Account | Connected to Claude Code on the web with at least one repository authenticated |

29| Slack Authentication | Your Slack account linked to your Claude account via the Claude app |29| Slack Authentication | Your Slack account linked to your Claude account via the Claude app |


64 In Code + Chat mode, if Claude routes a message to Chat but you wanted a coding session, you can click "Retry as Code" to create a Claude Code session instead. Similarly, if it's routed to Code but you wanted a Chat session, you can choose that option in that thread.64 In Code + Chat mode, if Claude routes a message to Chat but you wanted a coding session, you can click "Retry as Code" to create a Claude Code session instead. Similarly, if it's routed to Code but you wanted a Chat session, you can choose that option in that thread.

65 </Note>65 </Note>

66 </Step>66 </Step>

67 

68 <Step title="Add Claude to channels">

69 Claude is not automatically added to any channels after installation. To use Claude in a channel, invite it by typing `/invite @Claude` in that channel. Claude can only respond to @mentions in channels where it has been added.

70 </Step>

67</Steps>71</Steps>

68 72 

69## How it works73## How it works


127| Repository Access | Users can only access repositories they've personally connected |131| Repository Access | Users can only access repositories they've personally connected |

128| Session History | Sessions appear in your Claude Code history on claude.ai/code |132| Session History | Sessions appear in your Claude Code history on claude.ai/code |

129 133 

130### Workspace admin permissions134### Workspace-level access

135 

136Slack workspace administrators control whether the Claude app is available in their workspace:

137 

138| Control | Description |

139| :--------------------------- | :---------------------------------------------------------------------------------------------------------------- |

140| App installation | Workspace admins decide whether to install the Claude app from the Slack App Marketplace |

141| Enterprise Grid distribution | For Enterprise Grid organizations, organization admins can control which workspaces have access to the Claude app |

142| App removal | Removing the app from a workspace immediately revokes access for all users in that workspace |

131 143 

132Slack workspace administrators control whether the Claude app can be installed in the workspace. Individual users then authenticate with their own Claude accounts to use the integration.144### Channel-based access control

145 

146Claude is not automatically added to any channels after installation. Users must explicitly invite Claude to channels where they want to use it:

147 

148* **Invite required**: Type `/invite @Claude` in any channel to add Claude to that channel

149* **Channel membership controls access**: Claude can only respond to @mentions in channels where it has been added

150* **Access gating through channels**: Admins can control who uses Claude Code by managing which channels Claude is invited to and who has access to those channels

151* **Private channel support**: Claude works in both public and private channels, giving teams flexibility in controlling visibility

152 

153This channel-based model allows teams to restrict Claude Code usage to specific channels, providing an additional layer of access control beyond workspace-level permissions.

133 154 

134## What's accessible where155## What's accessible where

135 156 


137 158 

138**On the web**: The complete Claude Code session with full conversation history, all code changes, file operations, and the ability to continue the session or create pull requests.159**On the web**: The complete Claude Code session with full conversation history, all code changes, file operations, and the ability to continue the session or create pull requests.

139 160 

161For Enterprise and Team accounts, sessions created from Claude in Slack are

162automatically visible to the organization. See [Claude Code on the Web sharing](/en/claude-code-on-the-web#share-sessions)

163for more details.

164 

140## Best practices165## Best practices

141 166 

142### Writing effective requests167### Writing effective requests

statusline.md +957 −166

Details

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> 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.3> Use this file to discover all available pages before exploring further.

4 4 

5# Status line configuration5# Customize your status line

6 6 

7> Create a custom status line for Claude Code to display contextual information7> Configure a custom status bar to monitor context window usage, costs, and git status in Claude Code

8 8 

9Make Claude Code your own with a custom status line that displays at the bottom of the Claude Code interface, similar to how terminal prompts (PS1) work in shells like Oh-my-zsh.9The status line is a customizable bar at the bottom of Claude Code that runs any shell script you configure. It receives JSON session data on stdin and displays whatever your script prints, giving you a persistent, at-a-glance view of context usage, costs, git status, or anything else you want to track.

10 10 

11## Create a custom status line11Status lines are useful when you:

12 12 

13You can either:13* Want to monitor context window usage as you work

14* Need to track session costs

15* Work across multiple sessions and need to distinguish them

16* Want git branch and status always visible

14 17 

15* Run `/statusline` to ask Claude Code to help you set up a custom status line. By default, it will try to reproduce your terminal's prompt, but you can provide additional instructions about the behavior you want to Claude Code, such as `/statusline show the model name in orange`18Here's an example of a [multi-line status line](#display-multiple-lines) that displays git info on the first line and a color-coded context bar on the second.

16 19 

17* Directly add a `statusLine` command to your `.claude/settings.json`:20<Frame>

21 <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-multiline.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=60f11387658acc9ff75158ae85f2ac87" alt="A multi-line status line showing model name, directory, git branch on the first line, and a context usage progress bar with cost and duration on the second line" width="776" height="212" data-path="images/statusline-multiline.png" />

22</Frame>

23 

24This page walks through [setting up a basic status line](#set-up-a-status-line), explains [how the data flows](#how-status-lines-work) from Claude Code to your script, lists [all the fields you can display](#available-data), and provides [ready-to-use examples](#examples) for common patterns like git status, cost tracking, and progress bars.

25 

26## Set up a status line

27 

28Use the [`/statusline` command](#use-the-%2Fstatusline-command) to have Claude Code generate a script for you, or [manually create a script](#manually-configure-a-status-line) and add it to your settings.

29 

30### Use the /statusline command

31 

32The `/statusline` command accepts natural language instructions describing what you want displayed. Claude Code generates a script file in `~/.claude/` and updates your settings automatically:

33 

34```text theme={null}

35/statusline show model name and context percentage with a progress bar

36```

37 

38### Manually configure a status line

39 

40Add a `statusLine` field to your user settings (`~/.claude/settings.json`, where `~` is your home directory) or [project settings](/en/settings#settings-files). Set `type` to `"command"` and point `command` to a script path or an inline shell command. For a full walkthrough of creating a script, see [Build a status line step by step](#build-a-status-line-step-by-step).

18 41 

19```json theme={null}42```json theme={null}

20{43{

21 "statusLine": {44 "statusLine": {

22 "type": "command",45 "type": "command",

23 "command": "~/.claude/statusline.sh",46 "command": "~/.claude/statusline.sh",

24 "padding": 0 // Optional: set to 0 to let status line go to edge47 "padding": 2

25 }48 }

26}49}

27```50```

28 51 

29## How it Works52The `command` field runs in a shell, so you can also use inline commands instead of a script file. This example uses `jq` to parse the JSON input and display the model name and context percentage:

30 53 

31* The status line is updated when the conversation messages update54```json theme={null}

32* Updates run at most every 300 ms55{

33* The first line of stdout from your command becomes the status line text56 "statusLine": {

34* ANSI color codes are supported for styling your status line57 "type": "command",

35* Claude Code passes contextual information about the current session (model, directories, etc.) as JSON to your script via stdin58 "command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'"

59 }

60}

61```

36 62 

37## JSON Input Structure63The optional `padding` field adds extra horizontal spacing (in characters) to the status line content. Defaults to `0`. This padding is in addition to the interface's built-in spacing, so it controls relative indentation rather than absolute distance from the terminal edge.

38 64 

39Your status line command receives structured data via stdin in JSON format:65The optional `refreshInterval` field re-runs your command every N seconds in addition to the [event-driven updates](#how-status-lines-work). The minimum is `1`. Set this when your status line shows time-based data such as a clock, or when background subagents change git state while the main session is idle. Leave it unset to run only on events.

40 66 

41```json theme={null}67### Disable the status line

42{68 

43 "hook_event_name": "Status",69Run `/statusline` and ask it to remove or clear your status line (e.g., `/statusline delete`, `/statusline clear`, `/statusline remove it`). You can also manually delete the `statusLine` field from your settings.json.

44 "session_id": "abc123...",70 

45 "transcript_path": "/path/to/transcript.json",71## Build a status line step by step

72 

73This walkthrough shows what's happening under the hood by manually creating a status line that displays the current model, working directory, and context window usage percentage.

74 

75<Note>Running [`/statusline`](#use-the-%2Fstatusline-command) with a description of what you want configures all of this for you automatically.</Note>

76 

77These examples use Bash scripts, which work on macOS and Linux. On Windows, see [Windows configuration](#windows-configuration) for PowerShell and Git Bash examples.

78 

79<Frame>

80 <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-quickstart.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=696445e59ca0059213250651ad23db6b" alt="A status line showing model name, directory, and context percentage" width="726" height="164" data-path="images/statusline-quickstart.png" />

81</Frame>

82 

83<Steps>

84 <Step title="Create a script that reads JSON and prints output">

85 Claude Code sends JSON data to your script via stdin. This script uses [`jq`](https://jqlang.github.io/jq/), a command-line JSON parser you may need to install, to extract the model name, directory, and context percentage, then prints a formatted line.

86 

87 Save this to `~/.claude/statusline.sh` (where `~` is your home directory, such as `/Users/username` on macOS or `/home/username` on Linux):

88 

89 ```bash theme={null}

90 #!/bin/bash

91 # Read JSON data that Claude Code sends to stdin

92 input=$(cat)

93 

94 # Extract fields using jq

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

96 DIR=$(echo "$input" | jq -r '.workspace.current_dir')

97 # The "// 0" provides a fallback if the field is null

98 PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

99 

100 # Output the status line - ${DIR##*/} extracts just the folder name

101 echo "[$MODEL] 📁 ${DIR##*/} | ${PCT}% context"

102 ```

103 </Step>

104 

105 <Step title="Make it executable">

106 Mark the script as executable so your shell can run it:

107 

108 ```bash theme={null}

109 chmod +x ~/.claude/statusline.sh

110 ```

111 </Step>

112 

113 <Step title="Add to settings">

114 Tell Claude Code to run your script as the status line. Add this configuration to `~/.claude/settings.json`, which sets `type` to `"command"` (meaning "run this shell command") and points `command` to your script:

115 

116 ```json theme={null}

117 {

118 "statusLine": {

119 "type": "command",

120 "command": "~/.claude/statusline.sh"

121 }

122 }

123 ```

124 

125 Your status line appears at the bottom of the interface. Settings reload automatically, but changes won't appear until your next interaction with Claude Code.

126 </Step>

127</Steps>

128 

129## How status lines work

130 

131Claude Code runs your script and pipes [JSON session data](#available-data) to it via stdin. Your script reads the JSON, extracts what it needs, and prints text to stdout. Claude Code displays whatever your script prints.

132 

133**When it updates**

134 

135Your script runs after each new assistant message, when the permission mode changes, or when vim mode toggles. Updates are debounced at 300ms, meaning rapid changes batch together and your script runs once things settle. If a new update triggers while your script is still running, the in-flight execution is cancelled. If you edit your script, the changes won't appear until your next interaction with Claude Code triggers an update.

136 

137These triggers can go quiet when the main session is idle, for example while a coordinator waits on background subagents. To keep time-based or externally-sourced segments current during idle periods, set [`refreshInterval`](#manually-configure-a-status-line) to also re-run the command on a fixed timer.

138 

139**What your script can output**

140 

141* **Multiple lines**: each `echo` or `print` statement displays as a separate row. See the [multi-line example](#display-multiple-lines).

142* **Colors**: use [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) like `\033[32m` for green (terminal must support them). See the [git status example](#git-status-with-colors).

143* **Links**: use [OSC 8 escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code#OSC) to make text clickable (Cmd+click on macOS, Ctrl+click on Windows/Linux). Requires a terminal that supports hyperlinks like iTerm2, Kitty, or WezTerm. See the [clickable links example](#clickable-links).

144 

145<Note>The status line runs locally and does not consume API tokens. It temporarily hides during certain UI interactions, including autocomplete suggestions, the help menu, and permission prompts.</Note>

146 

147## Available data

148 

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

150 

151| Field | Description |

152| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

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

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

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

156| `workspace.added_dirs` | Additional directories added via `/add-dir` or `--add-dir`. Empty array if none have been added |

157| `workspace.git_worktree` | Git worktree name when the current directory is inside a linked worktree created with `git worktree add`. Absent in the main working tree. Populated for any git worktree, unlike `worktree.*` which applies only to `--worktree` sessions |

158| `cost.total_cost_usd` | Estimated session cost in USD, computed client-side. May differ from your actual bill |

159| `cost.total_duration_ms` | Total wall-clock time since the session started, in milliseconds |

160| `cost.total_api_duration_ms` | Total time spent waiting for API responses in milliseconds |

161| `cost.total_lines_added`, `cost.total_lines_removed` | Lines of code changed |

162| `context_window.total_input_tokens`, `context_window.total_output_tokens` | Cumulative token counts across the session |

163| `context_window.context_window_size` | Maximum context window size in tokens. 200000 by default, or 1000000 for models with extended context. |

164| `context_window.used_percentage` | Pre-calculated percentage of context window used |

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

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

167| `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. |

168| `effort.level` | Current reasoning effort (`low`, `medium`, `high`, `xhigh`, or `max`). Reflects the live session value, including mid-session `/effort` changes. Absent when the current model does not support the effort parameter |

169| `thinking.enabled` | Whether extended thinking is enabled for the session |

170| `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 |

171| `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 |

172| `session_id` | Unique session identifier |

173| `session_name` | Custom session name set with the `--name` flag or `/rename`. Absent if no custom name has been set |

174| `transcript_path` | Path to conversation transcript file |

175| `version` | Claude Code version |

176| `output_style.name` | Name of the current output style |

177| `vim.mode` | Current vim mode (`NORMAL`, `INSERT`, `VISUAL`, or `VISUAL LINE`) when [vim mode](/en/interactive-mode#vim-editor-mode) is enabled |

178| `agent.name` | Agent name when running with the `--agent` flag or agent settings configured |

179| `worktree.name` | Name of the active worktree. Present only during `--worktree` sessions |

180| `worktree.path` | Absolute path to the worktree directory |

181| `worktree.branch` | Git branch name for the worktree (for example, `"worktree-my-feature"`). Absent for hook-based worktrees |

182| `worktree.original_cwd` | The directory Claude was in before entering the worktree |

183| `worktree.original_branch` | Git branch checked out before entering the worktree. Absent for hook-based worktrees |

184 

185<Accordion title="Full JSON schema">

186 Your status line command receives this JSON structure via stdin:

187 

188 ```json theme={null}

189 {

46 "cwd": "/current/working/directory",190 "cwd": "/current/working/directory",

191 "session_id": "abc123...",

192 "session_name": "my-session",

193 "transcript_path": "/path/to/transcript.jsonl",

47 "model": {194 "model": {

48 "id": "claude-opus-4-1",195 "id": "claude-opus-4-7",

49 "display_name": "Opus"196 "display_name": "Opus"

50 },197 },

51 "workspace": {198 "workspace": {

52 "current_dir": "/current/working/directory",199 "current_dir": "/current/working/directory",

53 "project_dir": "/original/project/directory"200 "project_dir": "/original/project/directory",

201 "added_dirs": [],

202 "git_worktree": "feature-xyz"

54 },203 },

55 "version": "1.0.80",204 "version": "2.1.90",

56 "output_style": {205 "output_style": {

57 "name": "default"206 "name": "default"

58 },207 },


67 "total_input_tokens": 15234,216 "total_input_tokens": 15234,

68 "total_output_tokens": 4521,217 "total_output_tokens": 4521,

69 "context_window_size": 200000,218 "context_window_size": 200000,

70 "used_percentage": 42.5,219 "used_percentage": 8,

71 "remaining_percentage": 57.5,220 "remaining_percentage": 92,

72 "current_usage": {221 "current_usage": {

73 "input_tokens": 8500,222 "input_tokens": 8500,

74 "output_tokens": 1200,223 "output_tokens": 1200,

75 "cache_creation_input_tokens": 5000,224 "cache_creation_input_tokens": 5000,

76 "cache_read_input_tokens": 2000225 "cache_read_input_tokens": 2000

77 }226 }

227 },

228 "exceeds_200k_tokens": false,

229 "effort": {

230 "level": "high"

231 },

232 "thinking": {

233 "enabled": true

234 },

235 "rate_limits": {

236 "five_hour": {

237 "used_percentage": 23.5,

238 "resets_at": 1738425600

239 },

240 "seven_day": {

241 "used_percentage": 41.2,

242 "resets_at": 1738857600

78 }243 }

79}244 },

80```245 "vim": {

246 "mode": "NORMAL"

247 },

248 "agent": {

249 "name": "security-reviewer"

250 },

251 "worktree": {

252 "name": "my-feature",

253 "path": "/path/to/.claude/worktrees/my-feature",

254 "branch": "worktree-my-feature",

255 "original_cwd": "/path/to/project",

256 "original_branch": "main"

257 }

258 }

259 ```

81 260 

82## Example Scripts261 **Fields that may be absent** (not present in JSON):

83 262 

84### Simple Status Line263 * `session_name`: appears only when a custom name has been set with `--name` or `/rename`

264 * `workspace.git_worktree`: appears only when the current directory is inside a linked git worktree

265 * `effort`: appears only when the current model supports the reasoning effort parameter

266 * `vim`: appears only when vim mode is enabled

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

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

269 * `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.

85 270 

86```bash theme={null}271 **Fields that may be `null`**:

87#!/bin/bash

88# Read JSON input from stdin

89input=$(cat)

90 272 

91# Extract values using jq273 * `context_window.current_usage`: `null` before the first API call in a session

92MODEL_DISPLAY=$(echo "$input" | jq -r '.model.display_name')274 * `context_window.used_percentage`, `context_window.remaining_percentage`: may be `null` early in the session

93CURRENT_DIR=$(echo "$input" | jq -r '.workspace.current_dir')

94 275 

95echo "[$MODEL_DISPLAY] 📁 ${CURRENT_DIR##*/}"276 Handle missing fields with conditional access and null values with fallback defaults in your scripts.

96```277</Accordion>

278 

279### Context window fields

280 

281The `context_window` object provides two ways to track context usage:

97 282 

98### Git-Aware Status Line283* **Cumulative totals** (`total_input_tokens`, `total_output_tokens`): sum of all tokens across the entire session, useful for tracking total consumption

284* **Current usage** (`current_usage`): token counts from the most recent API call, use this for accurate context percentage since it reflects the actual context state

99 285 

100```bash theme={null}286The `current_usage` object contains:

101#!/bin/bash

102# Read JSON input from stdin

103input=$(cat)

104 287 

105# Extract values using jq288* `input_tokens`: input tokens in current context

106MODEL_DISPLAY=$(echo "$input" | jq -r '.model.display_name')289* `output_tokens`: output tokens generated

107CURRENT_DIR=$(echo "$input" | jq -r '.workspace.current_dir')290* `cache_creation_input_tokens`: tokens written to cache

291* `cache_read_input_tokens`: tokens read from cache

108 292 

109# Show git branch if in a git repo293The `used_percentage` field is calculated from input tokens only: `input_tokens + cache_creation_input_tokens + cache_read_input_tokens`. It does not include `output_tokens`.

110GIT_BRANCH=""294 

111if git rev-parse --git-dir > /dev/null 2>&1; then295If you calculate context percentage manually from `current_usage`, use the same input-only formula to match `used_percentage`.

296 

297The `current_usage` object is `null` before the first API call in a session.

298 

299## Examples

300 

301These examples show common status line patterns. To use any example:

302 

3031. Save the script to a file like `~/.claude/statusline.sh` (or `.py`/`.js`)

3042. Make it executable: `chmod +x ~/.claude/statusline.sh`

3053. Add the path to your [settings](#manually-configure-a-status-line)

306 

307The Bash examples use [`jq`](https://jqlang.github.io/jq/) to parse JSON. Python and Node.js have built-in JSON parsing.

308 

309### Context window usage

310 

311Display the current model and context window usage with a visual progress bar. Each script reads JSON from stdin, extracts the `used_percentage` field, and builds a 10-character bar where filled blocks (▓) represent usage:

312 

313<Frame>

314 <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-context-window-usage.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=15b58ab3602f036939145dde3165c6f7" alt="A status line showing model name and a progress bar with percentage" width="448" height="152" data-path="images/statusline-context-window-usage.png" />

315</Frame>

316 

317<CodeGroup>

318 ```bash Bash theme={null}

319 #!/bin/bash

320 # Read all of stdin into a variable

321 input=$(cat)

322 

323 # Extract fields with jq, "// 0" provides fallback for null

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

325 PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

326 

327 # Build progress bar: printf -v creates a run of spaces, then

328 # ${var// /▓} replaces each space with a block character

329 BAR_WIDTH=10

330 FILLED=$((PCT * BAR_WIDTH / 100))

331 EMPTY=$((BAR_WIDTH - FILLED))

332 BAR=""

333 [ "$FILLED" -gt 0 ] && printf -v FILL "%${FILLED}s" && BAR="${FILL// /▓}"

334 [ "$EMPTY" -gt 0 ] && printf -v PAD "%${EMPTY}s" && BAR="${BAR}${PAD// /░}"

335 

336 echo "[$MODEL] $BAR $PCT%"

337 ```

338 

339 ```python Python theme={null}

340 #!/usr/bin/env python3

341 import json, sys

342 

343 # json.load reads and parses stdin in one step

344 data = json.load(sys.stdin)

345 model = data['model']['display_name']

346 # "or 0" handles null values

347 pct = int(data.get('context_window', {}).get('used_percentage', 0) or 0)

348 

349 # String multiplication builds the bar

350 filled = pct * 10 // 100

351 bar = '▓' * filled + '░' * (10 - filled)

352 

353 print(f"[{model}] {bar} {pct}%")

354 ```

355 

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

357 #!/usr/bin/env node

358 // Node.js reads stdin asynchronously with events

359 let input = '';

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

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

362 const data = JSON.parse(input);

363 const model = data.model.display_name;

364 // Optional chaining (?.) safely handles null fields

365 const pct = Math.floor(data.context_window?.used_percentage || 0);

366 

367 // String.repeat() builds the bar

368 const filled = Math.floor(pct * 10 / 100);

369 const bar = '▓'.repeat(filled) + '░'.repeat(10 - filled);

370 

371 console.log(`[${model}] ${bar} ${pct}%`);

372 });

373 ```

374</CodeGroup>

375 

376### Git status with colors

377 

378Show git branch with color-coded indicators for staged and modified files. This script uses [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) for terminal colors: `\033[32m` is green, `\033[33m` is yellow, and `\033[0m` resets to default.

379 

380<Frame>

381 <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-git-context.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=e656f34f90d1d9a1d0e220988914345f" alt="A status line showing model, directory, git branch, and colored indicators for staged and modified files" width="742" height="178" data-path="images/statusline-git-context.png" />

382</Frame>

383 

384Each script checks if the current directory is a git repository, counts staged and modified files, and displays color-coded indicators:

385 

386<CodeGroup>

387 ```bash Bash theme={null}

388 #!/bin/bash

389 input=$(cat)

390 

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

392 DIR=$(echo "$input" | jq -r '.workspace.current_dir')

393 

394 GREEN='\033[32m'

395 YELLOW='\033[33m'

396 RESET='\033[0m'

397 

398 if git rev-parse --git-dir > /dev/null 2>&1; then

112 BRANCH=$(git branch --show-current 2>/dev/null)399 BRANCH=$(git branch --show-current 2>/dev/null)

113 if [ -n "$BRANCH" ]; then400 STAGED=$(git diff --cached --numstat 2>/dev/null | wc -l | tr -d ' ')

114 GIT_BRANCH=" | 🌿 $BRANCH"401 MODIFIED=$(git diff --numstat 2>/dev/null | wc -l | tr -d ' ')

115 fi

116fi

117 402 

118echo "[$MODEL_DISPLAY] 📁 ${CURRENT_DIR##*/}$GIT_BRANCH"403 GIT_STATUS=""

119```404 [ "$STAGED" -gt 0 ] && GIT_STATUS="${GREEN}+${STAGED}${RESET}"

405 [ "$MODIFIED" -gt 0 ] && GIT_STATUS="${GIT_STATUS}${YELLOW}~${MODIFIED}${RESET}"

120 406 

121### Python Example407 echo -e "[$MODEL] 📁 ${DIR##*/} | 🌿 $BRANCH $GIT_STATUS"

408 else

409 echo "[$MODEL] 📁 ${DIR##*/}"

410 fi

411 ```

122 412 

123```python theme={null}413 ```python Python theme={null}

124#!/usr/bin/env python3414 #!/usr/bin/env python3

125import json415 import json, sys, subprocess, os

126import sys

127import os

128 416 

129# Read JSON from stdin417 data = json.load(sys.stdin)

130data = json.load(sys.stdin)418 model = data['model']['display_name']

419 directory = os.path.basename(data['workspace']['current_dir'])

131 420 

132# Extract values421 GREEN, YELLOW, RESET = '\033[32m', '\033[33m', '\033[0m'

133model = data['model']['display_name']

134current_dir = os.path.basename(data['workspace']['current_dir'])

135 422 

136# Check for git branch

137git_branch = ""

138if os.path.exists('.git'):

139 try:423 try:

140 with open('.git/HEAD', 'r') as f:424 subprocess.check_output(['git', 'rev-parse', '--git-dir'], stderr=subprocess.DEVNULL)

141 ref = f.read().strip()425 branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True).strip()

142 if ref.startswith('ref: refs/heads/'):426 staged_output = subprocess.check_output(['git', 'diff', '--cached', '--numstat'], text=True).strip()

143 git_branch = f" | 🌿 {ref.replace('ref: refs/heads/', '')}"427 modified_output = subprocess.check_output(['git', 'diff', '--numstat'], text=True).strip()

428 staged = len(staged_output.split('\n')) if staged_output else 0

429 modified = len(modified_output.split('\n')) if modified_output else 0

430 

431 git_status = f"{GREEN}+{staged}{RESET}" if staged else ""

432 git_status += f"{YELLOW}~{modified}{RESET}" if modified else ""

433 

434 print(f"[{model}] 📁 {directory} | 🌿 {branch} {git_status}")

144 except:435 except:

145 pass436 print(f"[{model}] 📁 {directory}")

437 ```

146 438 

147print(f"[{model}] 📁 {current_dir}{git_branch}")439 ```javascript Node.js theme={null}

148```440 #!/usr/bin/env node

441 const { execSync } = require('child_process');

442 const path = require('path');

443 

444 let input = '';

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

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

447 const data = JSON.parse(input);

448 const model = data.model.display_name;

449 const dir = path.basename(data.workspace.current_dir);

450 

451 const GREEN = '\x1b[32m', YELLOW = '\x1b[33m', RESET = '\x1b[0m';

452 

453 try {

454 execSync('git rev-parse --git-dir', { stdio: 'ignore' });

455 const branch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();

456 const staged = execSync('git diff --cached --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;

457 const modified = execSync('git diff --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;

458 

459 let gitStatus = staged ? `${GREEN}+${staged}${RESET}` : '';

460 gitStatus += modified ? `${YELLOW}~${modified}${RESET}` : '';

461 

462 console.log(`[${model}] 📁 ${dir} | 🌿 ${branch} ${gitStatus}`);

463 } catch {

464 console.log(`[${model}] 📁 ${dir}`);

465 }

466 });

467 ```

468</CodeGroup>

469 

470### Cost and duration tracking

471 

472Track your session's API costs and elapsed time. The `cost.total_cost_usd` field accumulates the estimated cost of all API calls in the current session. The `cost.total_duration_ms` field measures total elapsed time since the session started, while `cost.total_api_duration_ms` tracks only the time spent waiting for API responses.

473 

474Each script formats cost as currency and converts milliseconds to minutes and seconds:

475 

476<Frame>

477 <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-cost-tracking.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=e3444a51fe6f3440c134bd5f1f08ad29" alt="A status line showing model name, session cost, and duration" width="588" height="180" data-path="images/statusline-cost-tracking.png" />

478</Frame>

479 

480<CodeGroup>

481 ```bash Bash theme={null}

482 #!/bin/bash

483 input=$(cat)

484 

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

486 COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')

487 DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')

488 

489 COST_FMT=$(printf '$%.2f' "$COST")

490 DURATION_SEC=$((DURATION_MS / 1000))

491 MINS=$((DURATION_SEC / 60))

492 SECS=$((DURATION_SEC % 60))

493 

494 echo "[$MODEL] 💰 $COST_FMT | ⏱️ ${MINS}m ${SECS}s"

495 ```

496 

497 ```python Python theme={null}

498 #!/usr/bin/env python3

499 import json, sys

500 

501 data = json.load(sys.stdin)

502 model = data['model']['display_name']

503 cost = data.get('cost', {}).get('total_cost_usd', 0) or 0

504 duration_ms = data.get('cost', {}).get('total_duration_ms', 0) or 0

505 

506 duration_sec = duration_ms // 1000

507 mins, secs = duration_sec // 60, duration_sec % 60

508 

509 print(f"[{model}] 💰 ${cost:.2f} | ⏱️ {mins}m {secs}s")

510 ```

511 

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

513 #!/usr/bin/env node

514 let input = '';

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

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

517 const data = JSON.parse(input);

518 const model = data.model.display_name;

519 const cost = data.cost?.total_cost_usd || 0;

520 const durationMs = data.cost?.total_duration_ms || 0;

521 

522 const durationSec = Math.floor(durationMs / 1000);

523 const mins = Math.floor(durationSec / 60);

524 const secs = durationSec % 60;

525 

526 console.log(`[${model}] 💰 $${cost.toFixed(2)} | ⏱️ ${mins}m ${secs}s`);

527 });

528 ```

529</CodeGroup>

530 

531### Display multiple lines

532 

533Your script can output multiple lines to create a richer display. Each `echo` statement produces a separate row in the status area.

534 

535<Frame>

536 <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-multiline.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=60f11387658acc9ff75158ae85f2ac87" alt="A multi-line status line showing model name, directory, git branch on the first line, and a context usage progress bar with cost and duration on the second line" width="776" height="212" data-path="images/statusline-multiline.png" />

537</Frame>

538 

539This example combines several techniques: threshold-based colors (green under 70%, yellow 70-89%, red 90%+), a progress bar, and git branch info. Each `print` or `echo` statement creates a separate row:

149 540 

150### Node.js Example541<CodeGroup>

542 ```bash Bash theme={null}

543 #!/bin/bash

544 input=$(cat)

151 545 

152```javascript theme={null}546 MODEL=$(echo "$input" | jq -r '.model.display_name')

153#!/usr/bin/env node547 DIR=$(echo "$input" | jq -r '.workspace.current_dir')

548 COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')

549 PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

550 DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')

154 551 

155const fs = require('fs');552 CYAN='\033[36m'; GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m'

156const path = require('path');

157 553 

158// Read JSON from stdin554 # Pick bar color based on context usage

159let input = '';555 if [ "$PCT" -ge 90 ]; then BAR_COLOR="$RED"

160process.stdin.on('data', chunk => input += chunk);556 elif [ "$PCT" -ge 70 ]; then BAR_COLOR="$YELLOW"

161process.stdin.on('end', () => {557 else BAR_COLOR="$GREEN"; fi

558 

559 FILLED=$((PCT / 10)); EMPTY=$((10 - FILLED))

560 printf -v FILL "%${FILLED}s"; printf -v PAD "%${EMPTY}s"

561 BAR="${FILL// /█}${PAD// /░}"

562 

563 MINS=$((DURATION_MS / 60000)); SECS=$(((DURATION_MS % 60000) / 1000))

564 

565 BRANCH=""

566 git rev-parse --git-dir > /dev/null 2>&1 && BRANCH=" | 🌿 $(git branch --show-current 2>/dev/null)"

567 

568 echo -e "${CYAN}[$MODEL]${RESET} 📁 ${DIR##*/}$BRANCH"

569 COST_FMT=$(printf '$%.2f' "$COST")

570 echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}% | ${YELLOW}${COST_FMT}${RESET} | ⏱️ ${MINS}m ${SECS}s"

571 ```

572 

573 ```python Python theme={null}

574 #!/usr/bin/env python3

575 import json, sys, subprocess, os

576 

577 data = json.load(sys.stdin)

578 model = data['model']['display_name']

579 directory = os.path.basename(data['workspace']['current_dir'])

580 cost = data.get('cost', {}).get('total_cost_usd', 0) or 0

581 pct = int(data.get('context_window', {}).get('used_percentage', 0) or 0)

582 duration_ms = data.get('cost', {}).get('total_duration_ms', 0) or 0

583 

584 CYAN, GREEN, YELLOW, RED, RESET = '\033[36m', '\033[32m', '\033[33m', '\033[31m', '\033[0m'

585 

586 bar_color = RED if pct >= 90 else YELLOW if pct >= 70 else GREEN

587 filled = pct // 10

588 bar = '█' * filled + '░' * (10 - filled)

589 

590 mins, secs = duration_ms // 60000, (duration_ms % 60000) // 1000

591 

592 try:

593 branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True, stderr=subprocess.DEVNULL).strip()

594 branch = f" | 🌿 {branch}" if branch else ""

595 except:

596 branch = ""

597 

598 print(f"{CYAN}[{model}]{RESET} 📁 {directory}{branch}")

599 print(f"{bar_color}{bar}{RESET} {pct}% | {YELLOW}${cost:.2f}{RESET} | ⏱️ {mins}m {secs}s")

600 ```

601 

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

603 #!/usr/bin/env node

604 const { execSync } = require('child_process');

605 const path = require('path');

606 

607 let input = '';

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

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

162 const data = JSON.parse(input);610 const data = JSON.parse(input);

611 const model = data.model.display_name;

612 const dir = path.basename(data.workspace.current_dir);

613 const cost = data.cost?.total_cost_usd || 0;

614 const pct = Math.floor(data.context_window?.used_percentage || 0);

615 const durationMs = data.cost?.total_duration_ms || 0;

616 

617 const CYAN = '\x1b[36m', GREEN = '\x1b[32m', YELLOW = '\x1b[33m', RED = '\x1b[31m', RESET = '\x1b[0m';

163 618 

164 // Extract values619 const barColor = pct >= 90 ? RED : pct >= 70 ? YELLOW : GREEN;

620 const filled = Math.floor(pct / 10);

621 const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);

622 

623 const mins = Math.floor(durationMs / 60000);

624 const secs = Math.floor((durationMs % 60000) / 1000);

625 

626 let branch = '';

627 try {

628 branch = execSync('git branch --show-current', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();

629 branch = branch ? ` | 🌿 ${branch}` : '';

630 } catch {}

631 

632 console.log(`${CYAN}[${model}]${RESET} 📁 ${dir}${branch}`);

633 console.log(`${barColor}${bar}${RESET} ${pct}% | ${YELLOW}$${cost.toFixed(2)}${RESET} | ⏱️ ${mins}m ${secs}s`);

634 });

635 ```

636</CodeGroup>

637 

638### Clickable links

639 

640This example creates a clickable link to your GitHub repository. It reads the git remote URL, converts SSH format to HTTPS with `sed`, and wraps the repo name in OSC 8 escape codes. Hold Cmd (macOS) or Ctrl (Windows/Linux) and click to open the link in your browser.

641 

642<Frame>

643 <img src="https://mintcdn.com/claude-code/nibzesLaJVh4ydOq/images/statusline-links.png?fit=max&auto=format&n=nibzesLaJVh4ydOq&q=85&s=4bcc6e7deb7cf52f41ab85a219b52661" alt="A status line showing a clickable link to a GitHub repository" width="726" height="198" data-path="images/statusline-links.png" />

644</Frame>

645 

646Each script gets the git remote URL, converts SSH format to HTTPS, and wraps the repo name in OSC 8 escape codes. The Bash version uses `printf '%b'` which interprets backslash escapes more reliably than `echo -e` across different shells:

647 

648<CodeGroup>

649 ```bash Bash theme={null}

650 #!/bin/bash

651 input=$(cat)

652 

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

654 

655 # Convert git SSH URL to HTTPS

656 REMOTE=$(git remote get-url origin 2>/dev/null | sed 's/git@github.com:/https:\/\/github.com\//' | sed 's/\.git$//')

657 

658 if [ -n "$REMOTE" ]; then

659 REPO_NAME=$(basename "$REMOTE")

660 # OSC 8 format: \e]8;;URL\a then TEXT then \e]8;;\a

661 # printf %b interprets escape sequences reliably across shells

662 printf '%b' "[$MODEL] 🔗 \e]8;;${REMOTE}\a${REPO_NAME}\e]8;;\a\n"

663 else

664 echo "[$MODEL]"

665 fi

666 ```

667 

668 ```python Python theme={null}

669 #!/usr/bin/env python3

670 import json, sys, subprocess, re, os

671 

672 data = json.load(sys.stdin)

673 model = data['model']['display_name']

674 

675 # Get git remote URL

676 try:

677 remote = subprocess.check_output(

678 ['git', 'remote', 'get-url', 'origin'],

679 stderr=subprocess.DEVNULL, text=True

680 ).strip()

681 # Convert SSH to HTTPS format

682 remote = re.sub(r'^git@github\.com:', 'https://github.com/', remote)

683 remote = re.sub(r'\.git$', '', remote)

684 repo_name = os.path.basename(remote)

685 # OSC 8 escape sequences

686 link = f"\033]8;;{remote}\a{repo_name}\033]8;;\a"

687 print(f"[{model}] 🔗 {link}")

688 except:

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

690 ```

691 

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

693 #!/usr/bin/env node

694 const { execSync } = require('child_process');

695 const path = require('path');

696 

697 let input = '';

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

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

700 const data = JSON.parse(input);

165 const model = data.model.display_name;701 const model = data.model.display_name;

166 const currentDir = path.basename(data.workspace.current_dir);

167 702 

168 // Check for git branch

169 let gitBranch = '';

170 try {703 try {

171 const headContent = fs.readFileSync('.git/HEAD', 'utf8').trim();704 let remote = execSync('git remote get-url origin', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();

172 if (headContent.startsWith('ref: refs/heads/')) {705 // Convert SSH to HTTPS format

173 gitBranch = ` | 🌿 ${headContent.replace('ref: refs/heads/', '')}`;706 remote = remote.replace(/^git@github\.com:/, 'https://github.com/').replace(/\.git$/, '');

707 const repoName = path.basename(remote);

708 // OSC 8 escape sequences

709 const link = `\x1b]8;;${remote}\x07${repoName}\x1b]8;;\x07`;

710 console.log(`[${model}] 🔗 ${link}`);

711 } catch {

712 console.log(`[${model}]`);

174 }713 }

175 } catch (e) {714 });

176 // Not a git repo or can't read HEAD715 ```

716</CodeGroup>

717 

718### Rate limit usage

719 

720Display 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).

721 

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

723 

724<CodeGroup>

725 ```bash Bash theme={null}

726 #!/bin/bash

727 input=$(cat)

728 

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

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

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

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

733 

734 LIMITS=""

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

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

737 

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

739 ```

740 

741 ```python Python theme={null}

742 #!/usr/bin/env python3

743 import json, sys

744 

745 data = json.load(sys.stdin)

746 model = data['model']['display_name']

747 

748 parts = []

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

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

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

752 

753 if five_h is not None:

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

755 if week is not None:

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

757 

758 if parts:

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

760 else:

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

762 ```

763 

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

765 #!/usr/bin/env node

766 let input = '';

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

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

769 const data = JSON.parse(input);

770 const model = data.model.display_name;

771 

772 const parts = [];

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

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

775 

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

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

778 

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

780 });

781 ```

782</CodeGroup>

783 

784### Cache expensive operations

785 

786Your 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.

787 

788The cache filename needs to be stable across status line invocations within a session, but unique across sessions so concurrent sessions in different repositories don't read each other's cached git state. Process-based identifiers like `$$`, `os.getpid()`, or `process.pid` change on every invocation and defeat the cache. Use the `session_id` from the JSON input instead: it's stable for the lifetime of a session and unique per session.

789 

790Each script checks if the cache file is missing or older than 5 seconds before running git commands:

791 

792<CodeGroup>

793 ```bash Bash theme={null}

794 #!/bin/bash

795 input=$(cat)

796 

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

798 DIR=$(echo "$input" | jq -r '.workspace.current_dir')

799 SESSION_ID=$(echo "$input" | jq -r '.session_id')

800 

801 CACHE_FILE="/tmp/statusline-git-cache-$SESSION_ID"

802 CACHE_MAX_AGE=5 # seconds

803 

804 cache_is_stale() {

805 [ ! -f "$CACHE_FILE" ] || \

806 # stat -f %m is macOS, stat -c %Y is Linux

807 [ $(($(date +%s) - $(stat -f %m "$CACHE_FILE" 2>/dev/null || stat -c %Y "$CACHE_FILE" 2>/dev/null || echo 0))) -gt $CACHE_MAX_AGE ]

177 }808 }

178 809 

179 console.log(`[${model}] 📁 ${currentDir}${gitBranch}`);810 if cache_is_stale; then

180});811 if git rev-parse --git-dir > /dev/null 2>&1; then

181```812 BRANCH=$(git branch --show-current 2>/dev/null)

813 STAGED=$(git diff --cached --numstat 2>/dev/null | wc -l | tr -d ' ')

814 MODIFIED=$(git diff --numstat 2>/dev/null | wc -l | tr -d ' ')

815 echo "$BRANCH|$STAGED|$MODIFIED" > "$CACHE_FILE"

816 else

817 echo "||" > "$CACHE_FILE"

818 fi

819 fi

182 820 

183### Helper Function Approach821 IFS='|' read -r BRANCH STAGED MODIFIED < "$CACHE_FILE"

184 

185For more complex bash scripts, you can create helper functions:

186 

187```bash theme={null}

188#!/bin/bash

189# Read JSON input once

190input=$(cat)

191 

192# Helper functions for common extractions

193get_model_name() { echo "$input" | jq -r '.model.display_name'; }

194get_current_dir() { echo "$input" | jq -r '.workspace.current_dir'; }

195get_project_dir() { echo "$input" | jq -r '.workspace.project_dir'; }

196get_version() { echo "$input" | jq -r '.version'; }

197get_cost() { echo "$input" | jq -r '.cost.total_cost_usd'; }

198get_duration() { echo "$input" | jq -r '.cost.total_duration_ms'; }

199get_lines_added() { echo "$input" | jq -r '.cost.total_lines_added'; }

200get_lines_removed() { echo "$input" | jq -r '.cost.total_lines_removed'; }

201get_input_tokens() { echo "$input" | jq -r '.context_window.total_input_tokens'; }

202get_output_tokens() { echo "$input" | jq -r '.context_window.total_output_tokens'; }

203get_context_window_size() { echo "$input" | jq -r '.context_window.context_window_size'; }

204 

205# Use the helpers

206MODEL=$(get_model_name)

207DIR=$(get_current_dir)

208echo "[$MODEL] 📁 ${DIR##*/}"

209```

210 822 

211### Context Window Usage823 if [ -n "$BRANCH" ]; then

824 echo "[$MODEL] 📁 ${DIR##*/} | 🌿 $BRANCH +$STAGED ~$MODIFIED"

825 else

826 echo "[$MODEL] 📁 ${DIR##*/}"

827 fi

828 ```

212 829 

213Display the percentage of context window consumed. The `context_window` object contains:830 ```python Python theme={null}

831 #!/usr/bin/env python3

832 import json, sys, subprocess, os, time

214 833 

215* `total_input_tokens` / `total_output_tokens`: Cumulative totals across the entire session834 data = json.load(sys.stdin)

216* `used_percentage`: Pre-calculated percentage of context window used (0-100)835 model = data['model']['display_name']

217* `remaining_percentage`: Pre-calculated percentage of context window remaining (0-100)836 directory = os.path.basename(data['workspace']['current_dir'])

218* `current_usage`: Current context window usage from the last API call (may be `null` if no messages yet)837 session_id = data['session_id']

219 * `input_tokens`: Input tokens in current context

220 * `output_tokens`: Output tokens generated

221 * `cache_creation_input_tokens`: Tokens written to cache

222 * `cache_read_input_tokens`: Tokens read from cache

223 838 

224You can use the pre-calculated `used_percentage` and `remaining_percentage` fields directly, or calculate from `current_usage` for more control.839 CACHE_FILE = f"/tmp/statusline-git-cache-{session_id}"

840 CACHE_MAX_AGE = 5 # seconds

225 841 

226**Simple approach using pre-calculated percentages:**842 def cache_is_stale():

843 if not os.path.exists(CACHE_FILE):

844 return True

845 return time.time() - os.path.getmtime(CACHE_FILE) > CACHE_MAX_AGE

227 846 

228```bash theme={null}847 if cache_is_stale():

229#!/bin/bash848 try:

230input=$(cat)849 subprocess.check_output(['git', 'rev-parse', '--git-dir'], stderr=subprocess.DEVNULL)

850 branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True).strip()

851 staged = subprocess.check_output(['git', 'diff', '--cached', '--numstat'], text=True).strip()

852 modified = subprocess.check_output(['git', 'diff', '--numstat'], text=True).strip()

853 staged_count = len(staged.split('\n')) if staged else 0

854 modified_count = len(modified.split('\n')) if modified else 0

855 with open(CACHE_FILE, 'w') as f:

856 f.write(f"{branch}|{staged_count}|{modified_count}")

857 except:

858 with open(CACHE_FILE, 'w') as f:

859 f.write("||")

231 860 

232MODEL=$(echo "$input" | jq -r '.model.display_name')861 with open(CACHE_FILE) as f:

233PERCENT_USED=$(echo "$input" | jq -r '.context_window.used_percentage // 0')862 branch, staged, modified = f.read().strip().split('|')

234 863 

235echo "[$MODEL] Context: ${PERCENT_USED}%"864 if branch:

236```865 print(f"[{model}] 📁 {directory} | 🌿 {branch} +{staged} ~{modified}")

866 else:

867 print(f"[{model}] 📁 {directory}")

868 ```

869 

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

871 #!/usr/bin/env node

872 const { execSync } = require('child_process');

873 const fs = require('fs');

874 const path = require('path');

875 

876 let input = '';

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

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

879 const data = JSON.parse(input);

880 const model = data.model.display_name;

881 const dir = path.basename(data.workspace.current_dir);

882 const sessionId = data.session_id;

883 

884 const CACHE_FILE = `/tmp/statusline-git-cache-${sessionId}`;

885 const CACHE_MAX_AGE = 5; // seconds

886 

887 const cacheIsStale = () => {

888 if (!fs.existsSync(CACHE_FILE)) return true;

889 return (Date.now() / 1000) - fs.statSync(CACHE_FILE).mtimeMs / 1000 > CACHE_MAX_AGE;

890 };

891 

892 if (cacheIsStale()) {

893 try {

894 execSync('git rev-parse --git-dir', { stdio: 'ignore' });

895 const branch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();

896 const staged = execSync('git diff --cached --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;

897 const modified = execSync('git diff --numstat', { encoding: 'utf8' }).trim().split('\n').filter(Boolean).length;

898 fs.writeFileSync(CACHE_FILE, `${branch}|${staged}|${modified}`);

899 } catch {

900 fs.writeFileSync(CACHE_FILE, '||');

901 }

902 }

237 903 

238**Advanced approach with manual calculation:**904 const [branch, staged, modified] = fs.readFileSync(CACHE_FILE, 'utf8').trim().split('|');

239 905 

240```bash theme={null}906 if (branch) {

241#!/bin/bash907 console.log(`[${model}] 📁 ${dir} | 🌿 ${branch} +${staged} ~${modified}`);

242input=$(cat)908 } else {

909 console.log(`[${model}] 📁 ${dir}`);

910 }

911 });

912 ```

913</CodeGroup>

914 

915### Windows configuration

916 

917On Windows, Claude Code runs status line commands through Git Bash. You can invoke PowerShell from that shell:

918 

919<CodeGroup>

920 ```json settings.json theme={null}

921 {

922 "statusLine": {

923 "type": "command",

924 "command": "powershell -NoProfile -File C:/Users/username/.claude/statusline.ps1"

925 }

926 }

927 ```

928 

929 ```powershell statusline.ps1 theme={null}

930 $input_json = $input | Out-String | ConvertFrom-Json

931 $cwd = $input_json.cwd

932 $model = $input_json.model.display_name

933 $used = $input_json.context_window.used_percentage

934 $dirname = Split-Path $cwd -Leaf

935 

936 if ($used) {

937 Write-Host "$dirname [$model] ctx: $used%"

938 } else {

939 Write-Host "$dirname [$model]"

940 }

941 ```

942</CodeGroup>

943 

944Or run a Bash script directly:

945 

946<CodeGroup>

947 ```json settings.json theme={null}

948 {

949 "statusLine": {

950 "type": "command",

951 "command": "~/.claude/statusline.sh"

952 }

953 }

954 ```

243 955 

244MODEL=$(echo "$input" | jq -r '.model.display_name')956 ```bash statusline.sh theme={null}

245CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size')957 #!/usr/bin/env bash

246USAGE=$(echo "$input" | jq '.context_window.current_usage')958 input=$(cat)

959 cwd=$(echo "$input" | grep -o '"cwd":"[^"]*"' | cut -d'"' -f4)

960 model=$(echo "$input" | grep -o '"display_name":"[^"]*"' | cut -d'"' -f4)

961 dirname="${cwd##*[/\\]}"

962 echo "$dirname [$model]"

963 ```

964</CodeGroup>

247 965 

248if [ "$USAGE" != "null" ]; then966## Subagent status lines

249 # Calculate current context from current_usage fields967 

250 CURRENT_TOKENS=$(echo "$USAGE" | jq '.input_tokens + .cache_creation_input_tokens + .cache_read_input_tokens')968The `subagentStatusLine` setting renders a custom row body for each [subagent](/en/sub-agents) shown in the agent panel below the prompt. Use it to replace the default `name · description · token count` row with your own formatting.

251 PERCENT_USED=$((CURRENT_TOKENS * 100 / CONTEXT_SIZE))969 

252 echo "[$MODEL] Context: ${PERCENT_USED}%"970```json theme={null}

253else971{

254 echo "[$MODEL] Context: 0%"972 "subagentStatusLine": {

255fi973 "type": "command",

974 "command": "~/.claude/subagent-statusline.sh"

975 }

976}

256```977```

257 978 

979The command runs once per refresh tick with all visible subagent rows passed as a single JSON object on stdin. The input includes the [base hook fields](/en/hooks#common-input-fields) plus `columns` (the usable row width) and a `tasks` array, where each task has `id`, `name`, `type`, `status`, `description`, `label`, `startTime`, `tokenCount`, `tokenSamples`, and `cwd`.

980 

981Write one JSON line to stdout per row you want to override, in the form `{"id": "<task id>", "content": "<row body>"}`. The `content` string is rendered as-is, including ANSI colors and OSC 8 hyperlinks. Omit a task's `id` to keep the default rendering for that row; emit an empty `content` string to hide it.

982 

983The same trust and `disableAllHooks` gates that apply to `statusLine` apply here. Plugins can ship a default `subagentStatusLine` in their [`settings.json`](/en/plugins-reference#standard-plugin-layout).

984 

258## Tips985## Tips

259 986 

260* Keep your status line concise - it should fit on one line987* **Test with mock input**: `echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/home/user/project"},"context_window":{"used_percentage":25},"session_id":"test-session-abc"}' | ./statusline.sh`

261* Use emojis (if your terminal supports them) and colors to make information scannable988* **Keep output short**: the status bar has limited width, so long output may get truncated or wrap awkwardly

262* Use `jq` for JSON parsing in Bash (see examples above)989* **Cache slow operations**: your script runs frequently during active sessions, so commands like `git status` can cause lag. See the [caching example](#cache-expensive-operations) for how to handle this.

263* Test your script by running it manually with mock JSON input: `echo '{"model":{"display_name":"Test"},"workspace":{"current_dir":"/test"}}' | ./statusline.sh`990 

264* Consider caching expensive operations (like git status) if needed991Community projects like [ccstatusline](https://github.com/sirmalloc/ccstatusline) and [starship-claude](https://github.com/martinemde/starship-claude) provide pre-built configurations with themes and additional features.

265 992 

266## Troubleshooting993## Troubleshooting

267 994 

268* If your status line doesn't appear, check that your script is executable (`chmod +x`)995**Status line not appearing**

269* Ensure your script outputs to stdout (not stderr)996 

997* Verify your script is executable: `chmod +x ~/.claude/statusline.sh`

998* Check that your script outputs to stdout, not stderr

999* Run your script manually to verify it produces output

1000* If `disableAllHooks` is set to `true` in your settings, the status line is also disabled. Remove this setting or set it to `false` to re-enable.

1001* Run `claude --debug` to log the exit code and stderr from the first status line invocation in a session

1002* Ask Claude to read your settings file and execute the `statusLine` command directly to surface errors

1003 

1004**Status line shows `--` or empty values**

1005 

1006* Fields may be `null` before the first API response completes

1007* Handle null values in your script with fallbacks such as `// 0` in jq

1008* Restart Claude Code if values remain empty after multiple messages

1009 

1010**Context percentage shows unexpected values**

1011 

1012* Use `used_percentage` for accurate context state rather than cumulative totals

1013* The `total_input_tokens` and `total_output_tokens` are cumulative across the session and may exceed the context window size

1014* Context percentage may differ from `/context` output due to when each is calculated

1015 

1016**OSC 8 links not clickable**

1017 

1018* Verify your terminal supports OSC 8 hyperlinks (iTerm2, Kitty, WezTerm)

1019 

1020* Terminal.app does not support clickable links

1021 

1022* If link text appears but isn't clickable, Claude Code may not have detected hyperlink support in your terminal. This commonly affects Windows Terminal and other emulators not in the auto-detection list. Set the `FORCE_HYPERLINK` environment variable to override detection before launching Claude Code:

1023 

1024 ```bash theme={null}

1025 FORCE_HYPERLINK=1 claude

1026 ```

1027 

1028 In PowerShell, set the variable in the current session first:

1029 

1030 ```powershell theme={null}

1031 $env:FORCE_HYPERLINK = "1"; claude

1032 ```

1033 

1034* SSH and tmux sessions may strip OSC sequences depending on configuration

1035 

1036* If escape sequences appear as literal text like `\e]8;;`, use `printf '%b'` instead of `echo -e` for more reliable escape handling

1037 

1038**Display glitches with escape sequences**

1039 

1040* Complex escape sequences (ANSI colors, OSC 8 links) can occasionally cause garbled output if they overlap with other UI updates

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

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

1043 

1044**Workspace trust required**

1045 

1046* 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.

1047* 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.

1048 

1049**Script errors or hangs**

1050 

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

1052* Slow scripts block the status line from updating until they complete. Keep scripts fast to avoid stale output.

1053* If a new update triggers while a slow script is running, the in-flight script is cancelled

1054* Test your script independently with mock input before configuring it

1055 

1056**Notifications share the status line row**

1057 

1058* System notifications like MCP server errors and auto-updates display on the right side of the same row as your status line. Transient notifications such as the context-low warning also cycle through this area.

1059* Enabling verbose mode adds a token counter to this area

1060* On narrow terminals, these notifications may truncate your status line output

sub-agents.md +325 −50

Details

6 6 

7> Create and use specialized AI subagents in Claude Code for task-specific workflows and improved context management.7> Create and use specialized AI subagents in Claude Code for task-specific workflows and improved context management.

8 8 

9Subagents are specialized AI assistants that handle specific types of tasks. Each subagent runs in its own context window with a custom system prompt, specific tool access, and independent permissions. When Claude encounters a task that matches a subagent's description, it delegates to that subagent, which works independently and returns results.9Subagents are specialized AI assistants that handle specific types of tasks. Use one when a side task would flood your main conversation with search results, logs, or file contents you won't reference again: the subagent does that work in its own context and returns only the summary. Define a custom subagent when you keep spawning the same kind of worker with the same instructions.

10 

11Each subagent runs in its own context window with a custom system prompt, specific tool access, and independent permissions. When Claude encounters a task that matches a subagent's description, it delegates to that subagent, which works independently and returns results. To see the context savings in practice, the [context window visualization](/en/context-window) walks through a session where a subagent handles research in its own separate window.

12 

13<Note>

14 If you need multiple agents working in parallel and communicating with each other, see [agent teams](/en/agent-teams) instead. Subagents work within a single session; agent teams coordinate across separate sessions.

15</Note>

10 16 

11Subagents help you:17Subagents help you:

12 18 


18 24 

19Claude uses each subagent's description to decide when to delegate tasks. When you create a subagent, write a clear description so Claude knows when to use it.25Claude uses each subagent's description to decide when to delegate tasks. When you create a subagent, write a clear description so Claude knows when to use it.

20 26 

21Claude Code includes several built-in subagents like **Explore**, **Plan**, and **general-purpose**. You can also create custom subagents to handle specific tasks. This page covers the [built-in subagents](#built-in-subagents), [how to create your own](#quickstart-create-your-first-subagent), [full configuration options](#configure-subagents), [patterns for working with subagents](#work-with-subagents), and [example subagents](#example-subagents).27Claude Code includes several built-in subagents like **Explore**, **Plan**, and **general-purpose**. You can also create custom subagents to handle specific tasks. This page covers:

28 

29* [Built-in subagents](#built-in-subagents)

30* [How to create your own](#quickstart-create-your-first-subagent)

31* [Full configuration options](#configure-subagents)

32* [Patterns for working with subagents](#work-with-subagents)

33* [Forked subagents](#fork-the-current-conversation)

34* [Example subagents](#example-subagents)

22 35 

23## Built-in subagents36## Built-in subagents

24 37 


61 Claude Code includes additional helper agents for specific tasks. These are typically invoked automatically, so you don't need to use them directly.74 Claude Code includes additional helper agents for specific tasks. These are typically invoked automatically, so you don't need to use them directly.

62 75 

63 | Agent | Model | When Claude uses it |76 | Agent | Model | When Claude uses it |

64 | :---------------- | :------- | :------------------------------------------------------- |77 | :---------------- | :----- | :------------------------------------------------------- |

65 | Bash | Inherits | Running terminal commands in a separate context |

66 | statusline-setup | Sonnet | When you run `/statusline` to configure your status line |78 | statusline-setup | Sonnet | When you run `/statusline` to configure your status line |

67 | Claude Code Guide | Haiku | When you ask questions about Claude Code features |79 | Claude Code Guide | Haiku | When you ask questions about Claude Code features |

68 </Tab>80 </Tab>


74 86 

75Subagents are defined in Markdown files with YAML frontmatter. You can [create them manually](#write-subagent-files) or use the `/agents` command.87Subagents are defined in Markdown files with YAML frontmatter. You can [create them manually](#write-subagent-files) or use the `/agents` command.

76 88 

77This walkthrough guides you through creating a user-level subagent with the `/agent` command. The subagent reviews code and suggests improvements for the codebase.89This walkthrough guides you through creating a user-level subagent with the `/agents` command. The subagent reviews code and suggests improvements for the codebase.

78 90 

79<Steps>91<Steps>

80 <Step title="Open the subagents interface">92 <Step title="Open the subagents interface">

81 In Claude Code, run:93 In Claude Code, run:

82 94 

83 ```95 ```text theme={null}

84 /agents96 /agents

85 ```97 ```

86 </Step>98 </Step>

87 99 

88 <Step title="Create a new user-level agent">100 <Step title="Choose a location">

89 Select **Create new agent**, then choose **User-level**. This saves the subagent to `~/.claude/agents/` so it's available in all your projects.101 Switch to the **Library** tab, select **Create new agent**, then choose **Personal**. This saves the subagent to `~/.claude/agents/` so it's available in all your projects.

90 </Step>102 </Step>

91 103 

92 <Step title="Generate with Claude">104 <Step title="Generate with Claude">

93 Select **Generate with Claude**. When prompted, describe the subagent:105 Select **Generate with Claude**. When prompted, describe the subagent:

94 106 

95 ```107 ```text theme={null}

96 A code improvement agent that scans files and suggests improvements108 A code improvement agent that scans files and suggests improvements

97 for readability, performance, and best practices. It should explain109 for readability, performance, and best practices. It should explain

98 each issue, show the current code, and provide an improved version.110 each issue, show the current code, and provide an improved version.

99 ```111 ```

100 112 

101 Claude generates the system prompt and configuration. Press `e` to open it in your editor if you want to customize it.113 Claude generates the identifier, description, and system prompt for you.

102 </Step>114 </Step>

103 115 

104 <Step title="Select tools">116 <Step title="Select tools">


113 Pick a background color for the subagent. This helps you identify which subagent is running in the UI.125 Pick a background color for the subagent. This helps you identify which subagent is running in the UI.

114 </Step>126 </Step>

115 127 

128 <Step title="Configure memory">

129 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.

130 </Step>

131 

116 <Step title="Save and try it out">132 <Step title="Save and try it out">

117 Save the subagent. It's available immediately (no restart needed). Try it:133 Review the configuration summary. Press `s` or `Enter` to save, or press `e` to save and edit the file in your editor. The subagent is available immediately. Try it:

118 134 

119 ```135 ```text theme={null}

120 Use the code-improver agent to suggest improvements in this project136 Use the code-improver agent to suggest improvements in this project

121 ```137 ```

122 138 


132 148 

133### Use the /agents command149### Use the /agents command

134 150 

135The `/agents` command provides an interactive interface for managing subagents. Run `/agents` to:151The `/agents` command opens a tabbed interface for managing subagents. The **Running** tab shows live subagents and lets you open or stop them. The **Library** tab lets you:

136 152 

137* View all available subagents (built-in, user, project, and plugin)153* View all available subagents (built-in, user, project, and plugin)

138* Create new subagents with guided setup or Claude generation154* Create new subagents with guided setup or Claude generation


142 158 

143This is the recommended way to create and manage subagents. For manual creation or automation, you can also add subagent files directly.159This is the recommended way to create and manage subagents. For manual creation or automation, you can also add subagent files directly.

144 160 

161To list all configured subagents from the command line without starting an interactive session, run `claude agents`. This shows agents grouped by source and indicates which are overridden by higher-priority definitions.

162 

145### Choose the subagent scope163### Choose the subagent scope

146 164 

147Subagents are Markdown files with YAML frontmatter. Store them in different locations depending on scope. When multiple subagents share the same name, the higher-priority location wins.165Subagents are Markdown files with YAML frontmatter. Store them in different locations depending on scope. When multiple subagents share the same name, the higher-priority location wins.

148 166 

149| Location | Scope | Priority | How to create |167| Location | Scope | Priority | How to create |

150| :--------------------------- | :---------------------- | :---------- | :------------------------------------ |168| :--------------------------- | :---------------------- | :---------- | :-------------------------------------------- |

151| `--agents` CLI flag | Current session | 1 (highest) | Pass JSON when launching Claude Code |169| Managed settings | Organization-wide | 1 (highest) | Deployed via [managed settings](/en/settings) |

152| `.claude/agents/` | Current project | 2 | Interactive or manual |170| `--agents` CLI flag | Current session | 2 | Pass JSON when launching Claude Code |

153| `~/.claude/agents/` | All your projects | 3 | Interactive or manual |171| `.claude/agents/` | Current project | 3 | Interactive or manual |

154| Plugin's `agents/` directory | Where plugin is enabled | 4 (lowest) | Installed with [plugins](/en/plugins) |172| `~/.claude/agents/` | All your projects | 4 | Interactive or manual |

173| Plugin's `agents/` directory | Where plugin is enabled | 5 (lowest) | Installed with [plugins](/en/plugins) |

155 174 

156**Project subagents** (`.claude/agents/`) are ideal for subagents specific to a codebase. Check them into version control so your team can use and improve them collaboratively.175**Project subagents** (`.claude/agents/`) are ideal for subagents specific to a codebase. Check them into version control so your team can use and improve them collaboratively.

157 176 

177Project subagents are discovered by walking up from the current working directory. Directories added with `--add-dir` [grant file access only](/en/permissions#additional-directories-grant-file-access-not-configuration) and are not scanned for subagents. To share subagents across projects, use `~/.claude/agents/` or a [plugin](/en/plugins).

178 

158**User subagents** (`~/.claude/agents/`) are personal subagents available in all your projects.179**User subagents** (`~/.claude/agents/`) are personal subagents available in all your projects.

159 180 

160**CLI-defined subagents** are passed as JSON when launching Claude Code. They exist only for that session and aren't saved to disk, making them useful for quick testing or automation scripts:181**CLI-defined subagents** are passed as JSON when launching Claude Code. They exist only for that session and aren't saved to disk, making them useful for quick testing or automation scripts. You can define multiple subagents in a single `--agents` call:

161 182 

162```bash theme={null}183```bash theme={null}

163claude --agents '{184claude --agents '{


166 "prompt": "You are a senior code reviewer. Focus on code quality, security, and best practices.",187 "prompt": "You are a senior code reviewer. Focus on code quality, security, and best practices.",

167 "tools": ["Read", "Grep", "Glob", "Bash"],188 "tools": ["Read", "Grep", "Glob", "Bash"],

168 "model": "sonnet"189 "model": "sonnet"

190 },

191 "debugger": {

192 "description": "Debugging specialist for errors and test failures.",

193 "prompt": "You are an expert debugger. Analyze errors, identify root causes, and provide fixes."

169 }194 }

170}'195}'

171```196```

172 197 

173The `--agents` flag accepts JSON with the same fields as [frontmatter](#supported-frontmatter-fields). Use `prompt` for the system prompt (equivalent to the markdown body in file-based subagents). See the [CLI reference](/en/cli-reference#agents-flag-format) for the full JSON format.198The `--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`, `initialPrompt`, `memory`, `effort`, `background`, `isolation`, and `color`. Use `prompt` for the system prompt, equivalent to the markdown body in file-based subagents.

199 

200**Managed subagents** are deployed by organization administrators. Place markdown files in `.claude/agents/` inside the [managed settings directory](/en/settings#settings-files), using the same frontmatter format as project and user subagents. Managed definitions take precedence over project and user subagents with the same name.

174 201 

175**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.202**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.

176 203 

204<Note>

205 For security reasons, plugin subagents do not support the `hooks`, `mcpServers`, or `permissionMode` frontmatter fields. These fields are ignored when loading agents from a plugin. If you need them, copy the agent file into `.claude/agents/` or `~/.claude/agents/`. You can also add rules to [`permissions.allow`](/en/settings#permission-settings) in `settings.json` or `settings.local.json`, but these rules apply to the entire session, not just the plugin subagent.

206</Note>

207 

208Subagent definitions from any of these scopes are also available to [agent teams](/en/agent-teams#use-subagent-definitions-for-teammates): when spawning a teammate, you can reference a subagent type and the teammate uses its `tools` and `model`, with the definition's body appended to the teammate's system prompt as additional instructions. See [agent teams](/en/agent-teams#use-subagent-definitions-for-teammates) for which frontmatter fields apply on that path.

209 

177### Write subagent files210### Write subagent files

178 211 

179Subagent files use YAML frontmatter for configuration, followed by the system prompt in Markdown:212Subagent files use YAML frontmatter for configuration, followed by the system prompt in Markdown:


196 229 

197The frontmatter defines the subagent's metadata and configuration. The body becomes the system prompt that guides the subagent's behavior. Subagents receive only this system prompt (plus basic environment details like working directory), not the full Claude Code system prompt.230The frontmatter defines the subagent's metadata and configuration. The body becomes the system prompt that guides the subagent's behavior. Subagents receive only this system prompt (plus basic environment details like working directory), not the full Claude Code system prompt.

198 231 

232A subagent starts in the main conversation's current working directory. Within a subagent, `cd` commands do not persist between Bash or PowerShell tool calls and do not affect the main conversation's working directory. To give the subagent an isolated copy of the repository instead, set [`isolation: worktree`](#supported-frontmatter-fields).

233 

199#### Supported frontmatter fields234#### Supported frontmatter fields

200 235 

201The following fields can be used in the YAML frontmatter. Only `name` and `description` are required.236The following fields can be used in the YAML frontmatter. Only `name` and `description` are required.

202 237 

203| Field | Required | Description |238| Field | Required | Description |

204| :---------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |239| :---------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

205| `name` | Yes | Unique identifier using lowercase letters and hyphens |240| `name` | Yes | Unique identifier using lowercase letters and hyphens |

206| `description` | Yes | When Claude should delegate to this subagent |241| `description` | Yes | When Claude should delegate to this subagent |

207| `tools` | No | [Tools](#available-tools) the subagent can use. Inherits all tools if omitted |242| `tools` | No | [Tools](#available-tools) the subagent can use. Inherits all tools if omitted |

208| `disallowedTools` | No | Tools to deny, removed from inherited or specified list |243| `disallowedTools` | No | Tools to deny, removed from inherited or specified list |

209| `model` | No | [Model](#choose-a-model) to use: `sonnet`, `opus`, `haiku`, or `inherit`. Defaults to `inherit` |244| `model` | No | [Model](#choose-a-model) to use: `sonnet`, `opus`, `haiku`, a full model ID (for example, `claude-opus-4-7`), or `inherit`. Defaults to `inherit` |

210| `permissionMode` | No | [Permission mode](#permission-modes): `default`, `acceptEdits`, `dontAsk`, `bypassPermissions`, or `plan` |245| `permissionMode` | No | [Permission mode](#permission-modes): `default`, `acceptEdits`, `auto`, `dontAsk`, `bypassPermissions`, or `plan` |

246| `maxTurns` | No | Maximum number of agentic turns before the subagent stops |

211| `skills` | No | [Skills](/en/skills) to load into the subagent's context at startup. The full skill content is injected, not just made available for invocation. Subagents don't inherit skills from the parent conversation |247| `skills` | No | [Skills](/en/skills) to load into the subagent's context at startup. The full skill content is injected, not just made available for invocation. Subagents don't inherit skills from the parent conversation |

248| `mcpServers` | No | [MCP servers](/en/mcp) available to this subagent. Each entry is either a server name referencing an already-configured server (e.g., `"slack"`) or an inline definition with the server name as key and a full [MCP server config](/en/mcp#installing-mcp-servers) as value |

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

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

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

252| `effort` | No | Effort level when this subagent is active. Overrides the session effort level. Default: inherits from session. Options: `low`, `medium`, `high`, `xhigh`, `max`; available levels depend on the model |

253| `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 |

254| `color` | No | Display color for the subagent in the task list and transcript. Accepts `red`, `blue`, `green`, `yellow`, `purple`, `orange`, `pink`, or `cyan` |

255| `initialPrompt` | No | Auto-submitted as the first user turn when this agent runs as the main session agent (via `--agent` or the `agent` setting). [Commands](/en/commands) and [skills](/en/skills) are processed. Prepended to any user-provided prompt |

213 256 

214### Choose a model257### Choose a model

215 258 

216The `model` field controls which [AI model](/en/model-config) the subagent uses:259The `model` field controls which [AI model](/en/model-config) the subagent uses:

217 260 

218* **Model alias**: Use one of the available aliases: `sonnet`, `opus`, or `haiku`261* **Model alias**: Use one of the available aliases: `sonnet`, `opus`, or `haiku`

262* **Full model ID**: Use a full model ID such as `claude-opus-4-7` or `claude-sonnet-4-6`. Accepts the same values as the `--model` flag

219* **inherit**: Use the same model as the main conversation263* **inherit**: Use the same model as the main conversation

220* **Omitted**: If not specified, defaults to `inherit` (uses the same model as the main conversation)264* **Omitted**: If not specified, defaults to `inherit` (uses the same model as the main conversation)

221 265 

266When Claude invokes a subagent, it can also pass a `model` parameter for that specific invocation. Claude Code resolves the subagent's model in this order:

267 

2681. The [`CLAUDE_CODE_SUBAGENT_MODEL`](/en/model-config#environment-variables) environment variable, if set

2692. The per-invocation `model` parameter

2703. The subagent definition's `model` frontmatter

2714. The main conversation's model

272 

222### Control subagent capabilities273### Control subagent capabilities

223 274 

224You can control what subagents can do through tool access, permission modes, and conditional rules.275You can control what subagents can do through tool access, permission modes, and conditional rules.

225 276 

226#### Available tools277#### Available tools

227 278 

228Subagents can use any of Claude Code's [internal tools](/en/settings#tools-available-to-claude). By default, subagents inherit all tools from the main conversation, including MCP tools.279Subagents 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.

229 280 

230To restrict tools, use the `tools` field (allowlist) or `disallowedTools` field (denylist):281To 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:

231 282 

232```yaml theme={null}283```yaml theme={null}

233---284---

234name: safe-researcher285name: safe-researcher

235description: Research agent with restricted capabilities286description: Research agent with restricted capabilities

236tools: Read, Grep, Glob, Bash287tools: Read, Grep, Glob, Bash

288---

289```

290 

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

292 

293```yaml theme={null}

294---

295name: no-writes

296description: Inherits every tool except file writes

237disallowedTools: Write, Edit297disallowedTools: Write, Edit

238---298---

239```299```

240 300 

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

302 

303#### Restrict which subagents can be spawned

304 

305When 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.

306 

307<Note>In version 2.1.63, the Task tool was renamed to Agent. Existing `Task(...)` references in settings and agent definitions still work as aliases.</Note>

308 

309```yaml theme={null}

310---

311name: coordinator

312description: Coordinates work across specialized agents

313tools: Agent(worker, researcher), Read, Bash

314---

315```

316 

317This is an allowlist: only the `worker` and `researcher` subagents can be spawned. If the agent tries to spawn any other type, the request fails and the agent sees only the allowed types in its prompt. To block specific agents while allowing all others, use [`permissions.deny`](#disable-specific-subagents) instead.

318 

319To allow spawning any subagent without restrictions, use `Agent` without parentheses:

320 

321```yaml theme={null}

322tools: Agent, Read, Bash

323```

324 

325If `Agent` is omitted from the `tools` list entirely, the agent cannot spawn any subagents. This restriction only applies to agents running as the main thread with `claude --agent`. Subagents cannot spawn other subagents, so `Agent(agent_type)` has no effect in subagent definitions.

326 

327#### Scope MCP servers to a subagent

328 

329Use the `mcpServers` field to give a subagent access to [MCP](/en/mcp) servers that aren't available in the main conversation. Inline servers defined here are connected when the subagent starts and disconnected when it finishes. String references share the parent session's connection.

330 

331<Note>

332 The `mcpServers` field applies in both contexts where an agent file can run:

333 

334 * As a subagent, spawned through the Agent tool or an @-mention

335 * As the main session, launched with [`--agent`](#invoke-subagents-explicitly) or the `agent` setting

336 

337 When the agent is the main session, inline server definitions connect at startup alongside servers from [`.mcp.json`](/en/mcp) and settings files.

338</Note>

339 

340Each entry in the list is either an inline server definition or a string referencing an MCP server already configured in your session:

341 

342```yaml theme={null}

343---

344name: browser-tester

345description: Tests features in a real browser using Playwright

346mcpServers:

347 # Inline definition: scoped to this subagent only

348 - playwright:

349 type: stdio

350 command: npx

351 args: ["-y", "@playwright/mcp@latest"]

352 # Reference by name: reuses an already-configured server

353 - github

354---

355 

356Use the Playwright tools to navigate, screenshot, and interact with pages.

357```

358 

359Inline definitions use the same schema as `.mcp.json` server entries (`stdio`, `http`, `sse`, `ws`), keyed by the server name.

360 

361To keep an MCP server out of the main conversation entirely and avoid its tool descriptions consuming context there, define it inline here rather than in `.mcp.json`. The subagent gets the tools; the parent conversation does not.

362 

241#### Permission modes363#### Permission modes

242 364 

243The `permissionMode` field controls how the subagent handles permission prompts. Subagents inherit the permission context from the main conversation but can override the mode.365The `permissionMode` field controls how the subagent handles permission prompts. Subagents inherit the permission context from the main conversation and can override the mode, except when the parent mode takes precedence as described below.

244 366 

245| Mode | Behavior |367| Mode | Behavior |

246| :------------------ | :----------------------------------------------------------------- |368| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------ |

247| `default` | Standard permission checking with prompts |369| `default` | Standard permission checking with prompts |

248| `acceptEdits` | Auto-accept file edits |370| `acceptEdits` | Auto-accept file edits and common filesystem commands for paths in the working directory or `additionalDirectories` |

371| `auto` | [Auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode): a background classifier reviews commands and protected-directory writes |

249| `dontAsk` | Auto-deny permission prompts (explicitly allowed tools still work) |372| `dontAsk` | Auto-deny permission prompts (explicitly allowed tools still work) |

250| `bypassPermissions` | Skip all permission checks |373| `bypassPermissions` | Skip permission prompts |

251| `plan` | Plan mode (read-only exploration) |374| `plan` | Plan mode (read-only exploration) |

252 375 

253<Warning>376<Warning>

254 Use `bypassPermissions` with caution. It skips all permission checks, allowing the subagent to execute any operation without approval.377 Use `bypassPermissions` with caution. It skips permission prompts, allowing the subagent to execute operations without approval. Writes to `.git`, `.claude`, `.vscode`, `.idea`, and `.husky` directories still prompt for confirmation, except for `.claude/commands`, `.claude/agents`, and `.claude/skills`. See [permission modes](/en/permission-modes#skip-all-checks-with-bypasspermissions-mode) for details.

255</Warning>378</Warning>

256 379 

257If the parent uses `bypassPermissions`, this takes precedence and cannot be overridden.380If the parent uses `bypassPermissions` or `acceptEdits`, this takes precedence and cannot be overridden. If the parent uses [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode), the subagent inherits auto mode and any `permissionMode` in its frontmatter is ignored: the classifier evaluates the subagent's tool calls with the same block and allow rules as the parent session.

258 381 

259#### Preload skills into subagents382#### Preload skills into subagents

260 383 


274 397 

275The full content of each skill is injected into the subagent's context, not just made available for invocation. Subagents don't inherit skills from the parent conversation; you must list them explicitly.398The full content of each skill is injected into the subagent's context, not just made available for invocation. Subagents don't inherit skills from the parent conversation; you must list them explicitly.

276 399 

400You cannot preload skills that set [`disable-model-invocation: true`](/en/skills#control-who-invokes-a-skill), since preloading draws from the same set of skills Claude can invoke. If a listed skill is missing or disabled, Claude Code skips it and logs a warning to the debug log.

401 

277<Note>402<Note>

278 This is the inverse of [running a skill in a subagent](/en/skills#run-skills-in-a-subagent). With `skills` in a subagent, the subagent controls the system prompt and loads skill content. With `context: fork` in a skill, the skill content is injected into the agent you specify. Both use the same underlying system.403 This is the inverse of [running a skill in a subagent](/en/skills#run-skills-in-a-subagent). With `skills` in a subagent, the subagent controls the system prompt and loads skill content. With `context: fork` in a skill, the skill content is injected into the agent you specify. Both use the same underlying system.

279</Note>404</Note>

280 405 

406#### Enable persistent memory

407 

408The `memory` field gives the subagent a persistent directory that survives across conversations. The subagent uses this directory to build up knowledge over time, such as codebase patterns, debugging insights, and architectural decisions.

409 

410```yaml theme={null}

411---

412name: code-reviewer

413description: Reviews code for quality and best practices

414memory: user

415---

416 

417You are a code reviewer. As you review code, update your agent memory with

418patterns, conventions, and recurring issues you discover.

419```

420 

421Choose a scope based on how broadly the memory should apply:

422 

423| Scope | Location | Use when |

424| :-------- | :-------------------------------------------- | :------------------------------------------------------------------------------------------ |

425| `user` | `~/.claude/agent-memory/<name-of-agent>/` | the subagent should remember learnings across all projects |

426| `project` | `.claude/agent-memory/<name-of-agent>/` | the subagent's knowledge is project-specific and shareable via version control |

427| `local` | `.claude/agent-memory-local/<name-of-agent>/` | the subagent's knowledge is project-specific but should not be checked into version control |

428 

429When memory is enabled:

430 

431* The subagent's system prompt includes instructions for reading and writing to the memory directory.

432* The subagent's system prompt also includes the first 200 lines or 25KB of `MEMORY.md` in the memory directory, whichever comes first, with instructions to curate `MEMORY.md` if it exceeds that limit.

433* Read, Write, and Edit tools are automatically enabled so the subagent can manage its memory files.

434 

435##### Persistent memory tips

436 

437* `project` is the recommended default scope. It makes subagent knowledge shareable via version control. Use `user` when the subagent's knowledge is broadly applicable across projects, or `local` when the knowledge should not be checked into version control.

438* Ask the subagent to consult its memory before starting work: "Review this PR, and check your memory for patterns you've seen before."

439* Ask the subagent to update its memory after completing a task: "Now that you're done, save what you learned to your memory." Over time, this builds a knowledge base that makes the subagent more effective.

440* Include memory instructions directly in the subagent's markdown file so it proactively maintains its own knowledge base:

441 

442 ```markdown theme={null}

443 Update your agent memory as you discover codepaths, patterns, library

444 locations, and key architectural decisions. This builds up institutional

445 knowledge across conversations. Write concise notes about what you found

446 and where.

447 ```

448 

281#### Conditional rules with hooks449#### Conditional rules with hooks

282 450 

283For more dynamic control over tool usage, use `PreToolUse` hooks to validate operations before they execute. This is useful when you need to allow some operations of a tool while blocking others.451For more dynamic control over tool usage, use `PreToolUse` hooks to validate operations before they execute. This is useful when you need to allow some operations of a tool while blocking others.


320 488 

321#### Disable specific subagents489#### Disable specific subagents

322 490 

323You can prevent Claude from using specific subagents by adding them to the `deny` array in your [settings](/en/settings#permission-settings). Use the format `Task(subagent-name)` where `subagent-name` matches the subagent's name field.491You can prevent Claude from using specific subagents by adding them to the `deny` array in your [settings](/en/settings#permission-settings). Use the format `Agent(subagent-name)` where `subagent-name` matches the subagent's name field.

324 492 

325```json theme={null}493```json theme={null}

326{494{

327 "permissions": {495 "permissions": {

328 "deny": ["Task(Explore)", "Task(my-custom-agent)"]496 "deny": ["Agent(Explore)", "Agent(my-custom-agent)"]

329 }497 }

330}498}

331```499```


333This works for both built-in and custom subagents. You can also use the `--disallowedTools` CLI flag:501This works for both built-in and custom subagents. You can also use the `--disallowedTools` CLI flag:

334 502 

335```bash theme={null}503```bash theme={null}

336claude --disallowedTools "Task(Explore)"504claude --disallowedTools "Agent(Explore)"

337```505```

338 506 

339See [IAM documentation](/en/iam#tool-specific-permission-rules) for more details on permission rules.507See [Permissions documentation](/en/permissions#tool-specific-permission-rules) for more details on permission rules.

340 508 

341### Define hooks for subagents509### Define hooks for subagents

342 510 


349 517 

350Define hooks directly in the subagent's markdown file. These hooks only run while that specific subagent is active and are cleaned up when it finishes.518Define hooks directly in the subagent's markdown file. These hooks only run while that specific subagent is active and are cleaned up when it finishes.

351 519 

520<Note>

521 Frontmatter hooks fire when the agent is spawned as a subagent through the Agent tool or an @-mention, and when the agent runs as the main session via [`--agent`](#invoke-subagents-explicitly) or the `agent` setting. In the main-session case they run alongside any hooks defined in [`settings.json`](/en/hooks).

522</Note>

523 

352All [hook events](/en/hooks#hook-events) are supported. The most common events for subagents are:524All [hook events](/en/hooks#hook-events) are supported. The most common events for subagents are:

353 525 

354| Event | Matcher input | When it fires |526| Event | Matcher input | When it fires |


377---549---

378```550```

379 551 

380`Stop` hooks in frontmatter are automatically converted to `SubagentStop` events.552When the agent is invoked as a subagent, `Stop` hooks in frontmatter are automatically converted to `SubagentStop` events.

381 553 

382#### Project-level hooks for subagent events554#### Project-level hooks for subagent events

383 555 


386| Event | Matcher input | When it fires |558| Event | Matcher input | When it fires |

387| :-------------- | :-------------- | :------------------------------- |559| :-------------- | :-------------- | :------------------------------- |

388| `SubagentStart` | Agent type name | When a subagent begins execution |560| `SubagentStart` | Agent type name | When a subagent begins execution |

389| `SubagentStop` | (none) | When any subagent completes |561| `SubagentStop` | Agent type name | When a subagent completes |

390 562 

391`SubagentStart` supports matchers to target specific agent types by name. `SubagentStop` fires for all subagent completions regardless of matcher values. This example runs a setup script only when the `db-agent` subagent starts, and a cleanup script when any subagent stops:563Both events support matchers to target specific agent types by name. This example runs a setup script only when the `db-agent` subagent starts, and a cleanup script when any subagent stops:

392 564 

393```json theme={null}565```json theme={null}

394{566{


420 592 

421Claude automatically delegates tasks based on the task description in your request, the `description` field in subagent configurations, and current context. To encourage proactive delegation, include phrases like "use proactively" in your subagent's description field.593Claude automatically delegates tasks based on the task description in your request, the `description` field in subagent configurations, and current context. To encourage proactive delegation, include phrases like "use proactively" in your subagent's description field.

422 594 

423You can also request a specific subagent explicitly:595### Invoke subagents explicitly

424 596 

425```597When automatic delegation isn't enough, you can request a subagent yourself. Three patterns escalate from a one-off suggestion to a session-wide default:

598 

599* **Natural language**: name the subagent in your prompt; Claude decides whether to delegate

600* **@-mention**: guarantees the subagent runs for one task

601* **Session-wide**: the whole session uses that subagent's system prompt, tool restrictions, and model via the `--agent` flag or the `agent` setting

602 

603For natural language, there's no special syntax. Name the subagent and Claude typically delegates:

604 

605```text theme={null}

426Use the test-runner subagent to fix failing tests606Use the test-runner subagent to fix failing tests

427Have the code-reviewer subagent look at my recent changes607Have the code-reviewer subagent look at my recent changes

428```608```

429 609 

610**@-mention the subagent.** Type `@` and pick the subagent from the typeahead, the same way you @-mention files. This ensures that specific subagent runs rather than leaving the choice to Claude:

611 

612```text theme={null}

613@"code-reviewer (agent)" look at the auth changes

614```

615 

616Your full message still goes to Claude, which writes the subagent's task prompt based on what you asked. The @-mention controls which subagent Claude invokes, not what prompt it receives.

617 

618Subagents provided by an enabled [plugin](/en/plugins) appear in the typeahead as `<plugin-name>:<agent-name>`. Named background subagents currently running in the session also appear in the typeahead, showing their status next to the name. You can also type the mention manually without using the picker: `@agent-<name>` for local subagents, or `@agent-<plugin-name>:<agent-name>` for plugin subagents.

619 

620**Run the whole session as a subagent.** Pass [`--agent <name>`](/en/cli-reference) to start a session where the main thread itself takes on that subagent's system prompt, tool restrictions, and model:

621 

622```bash theme={null}

623claude --agent code-reviewer

624```

625 

626The subagent's system prompt replaces the default Claude Code system prompt entirely, the same way [`--system-prompt`](/en/cli-reference) does. `CLAUDE.md` files and project memory still load through the normal message flow. The agent name appears as `@<name>` in the startup header so you can confirm it's active.

627 

628This works with built-in and custom subagents, and the choice persists when you resume the session.

629 

630For a plugin-provided subagent, pass the scoped name: `claude --agent <plugin-name>:<agent-name>`.

631 

632To make it the default for every session in a project, set `agent` in `.claude/settings.json`:

633 

634```json theme={null}

635{

636 "agent": "code-reviewer"

637}

638```

639 

640The CLI flag overrides the setting if both are present.

641 

430### Run subagents in foreground or background642### Run subagents in foreground or background

431 643 

432Subagents can run in the foreground (blocking) or background (concurrent):644Subagents can run in the foreground (blocking) or background (concurrent):

433 645 

434* **Foreground subagents** block the main conversation until complete. Permission prompts and clarifying questions (like [`AskUserQuestion`](/en/settings#tools-available-to-claude)) are passed through to you.646* **Foreground subagents** block the main conversation until complete. Permission prompts and clarifying questions (like [`AskUserQuestion`](/en/tools-reference)) are passed through to you.

435* **Background subagents** run concurrently while you continue working. Before launching, Claude Code prompts for any tool permissions the subagent will need, ensuring it has the necessary approvals upfront. Once running, the subagent inherits these permissions and auto-denies anything not pre-approved. If a background subagent needs to ask clarifying questions, that tool call fails but the subagent continues. MCP tools are not available in background subagents.647* **Background subagents** run concurrently while you continue working. Before launching, Claude Code prompts for any tool permissions the subagent will need, ensuring it has the necessary approvals upfront. Once running, the subagent inherits these permissions and auto-denies anything not pre-approved. If a background subagent needs to ask clarifying questions, that tool call fails but the subagent continues.

436 648 

437If a background subagent fails due to missing permissions, you can [resume it](#resume-subagents) in the foreground to retry with interactive prompts.649If a background subagent fails due to missing permissions, you can start a new foreground subagent with the same task to retry with interactive prompts.

438 650 

439Claude decides whether to run subagents in the foreground or background based on the task. You can also:651Claude decides whether to run subagents in the foreground or background based on the task. You can also:

440 652 

441* Ask Claude to "run this in the background"653* Ask Claude to "run this in the background"

442* Press **Ctrl+B** to background a running task654* Press **Ctrl+B** to background a running task

443 655 

444To disable all background task functionality, set the `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` environment variable to `1`. See [Environment variables](/en/settings#environment-variables).656To disable all background task functionality, set the `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` environment variable to `1`. See [Environment variables](/en/env-vars).

657 

658When [fork mode](#fork-the-current-conversation) is enabled, every subagent spawn runs in the background regardless of the `background` field. Forks still surface permission prompts in your terminal as they occur instead of pre-approving; named subagents follow the pre-approval flow above.

445 659 

446### Common patterns660### Common patterns

447 661 


449 663 

450One of the most effective uses for subagents is isolating operations that produce large amounts of output. Running tests, fetching documentation, or processing log files can consume significant context. By delegating these to a subagent, the verbose output stays in the subagent's context while only the relevant summary returns to your main conversation.664One of the most effective uses for subagents is isolating operations that produce large amounts of output. Running tests, fetching documentation, or processing log files can consume significant context. By delegating these to a subagent, the verbose output stays in the subagent's context while only the relevant summary returns to your main conversation.

451 665 

452```666```text theme={null}

453Use a subagent to run the test suite and report only the failing tests with their error messages667Use a subagent to run the test suite and report only the failing tests with their error messages

454```668```

455 669 


457 671 

458For independent investigations, spawn multiple subagents to work simultaneously:672For independent investigations, spawn multiple subagents to work simultaneously:

459 673 

460```674```text theme={null}

461Research the authentication, database, and API modules in parallel using separate subagents675Research the authentication, database, and API modules in parallel using separate subagents

462```676```

463 677 


467 When subagents complete, their results return to your main conversation. Running many subagents that each return detailed results can consume significant context.681 When subagents complete, their results return to your main conversation. Running many subagents that each return detailed results can consume significant context.

468</Warning>682</Warning>

469 683 

684For tasks that need sustained parallelism or exceed your context window, [agent teams](/en/agent-teams) give each worker its own independent context.

685 

470#### Chain subagents686#### Chain subagents

471 687 

472For multi-step workflows, ask Claude to use subagents in sequence. Each subagent completes its task and returns results to Claude, which then passes relevant context to the next subagent.688For multi-step workflows, ask Claude to use subagents in sequence. Each subagent completes its task and returns results to Claude, which then passes relevant context to the next subagent.

473 689 

474```690```text theme={null}

475Use the code-reviewer subagent to find performance issues, then use the optimizer subagent to fix them691Use the code-reviewer subagent to find performance issues, then use the optimizer subagent to fix them

476```692```

477 693 


492 708 

493Consider [Skills](/en/skills) instead when you want reusable prompts or workflows that run in the main conversation context rather than isolated subagent context.709Consider [Skills](/en/skills) instead when you want reusable prompts or workflows that run in the main conversation context rather than isolated subagent context.

494 710 

711For a quick question about something already in your conversation, use [`/btw`](/en/interactive-mode#side-questions-with-%2Fbtw) instead of a subagent. It sees your full context but has no tool access, and the answer is discarded rather than added to history.

712 

495<Note>713<Note>

496 Subagents cannot spawn other subagents. If your workflow requires nested delegation, use [Skills](/en/skills) or [chain subagents](#chain-subagents) from the main conversation.714 Subagents cannot spawn other subagents. If your workflow requires nested delegation, use [Skills](/en/skills) or [chain subagents](#chain-subagents) from the main conversation.

497</Note>715</Note>


504 722 

505Resumed subagents retain their full conversation history, including all previous tool calls, results, and reasoning. The subagent picks up exactly where it stopped rather than starting fresh.723Resumed subagents retain their full conversation history, including all previous tool calls, results, and reasoning. The subagent picks up exactly where it stopped rather than starting fresh.

506 724 

507When a subagent completes, Claude receives its agent ID. To resume a subagent, ask Claude to continue the previous work:725When a subagent completes, Claude receives its agent ID. Claude uses the `SendMessage` tool with the agent's ID as the `to` field to resume it. The `SendMessage` tool is only available when [agent teams](/en/agent-teams) are enabled via `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`.

508 726 

509```727To resume a subagent, ask Claude to continue the previous work:

728 

729```text theme={null}

510Use the code-reviewer subagent to review the authentication module730Use the code-reviewer subagent to review the authentication module

511[Agent completes]731[Agent completes]

512 732 


514[Claude resumes the subagent with full context from previous conversation]734[Claude resumes the subagent with full context from previous conversation]

515```735```

516 736 

737If a stopped subagent receives a `SendMessage`, it auto-resumes in the background without requiring a new `Agent` invocation.

738 

517You can also ask Claude for the agent ID if you want to reference it explicitly, or find IDs in the transcript files at `~/.claude/projects/{project}/{sessionId}/subagents/`. Each transcript is stored as `agent-{agentId}.jsonl`.739You can also ask Claude for the agent ID if you want to reference it explicitly, or find IDs in the transcript files at `~/.claude/projects/{project}/{sessionId}/subagents/`. Each transcript is stored as `agent-{agentId}.jsonl`.

518 740 

519Subagent transcripts persist independently of the main conversation:741Subagent transcripts persist independently of the main conversation:


524 746 

525#### Auto-compaction747#### Auto-compaction

526 748 

527Subagents support automatic compaction using the same logic as the main conversation. By default, auto-compaction triggers at approximately 95% capacity. To trigger compaction earlier, set `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` to a lower percentage (for example, `50`). See [environment variables](/en/settings#environment-variables) for details.749Subagents support automatic compaction using the same logic as the main conversation. By default, auto-compaction triggers at approximately 95% capacity. To trigger compaction earlier, set `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` to a lower percentage (for example, `50`). See [environment variables](/en/env-vars) for details.

528 750 

529Compaction events are logged in subagent transcript files:751Compaction events are logged in subagent transcript files:

530 752 


541 763 

542The `preTokens` value shows how many tokens were used before compaction occurred.764The `preTokens` value shows how many tokens were used before compaction occurred.

543 765 

766## Fork the current conversation

767 

768<Note>

769 Forked subagents are experimental and require Claude Code v2.1.117 or later. Behavior and configuration may change in future releases. Enable them by setting the [`CLAUDE_CODE_FORK_SUBAGENT`](/en/env-vars) environment variable to `1`.

770</Note>

771 

772A fork is a subagent that inherits the entire conversation so far instead of starting fresh. This drops the input isolation that subagents otherwise provide: a fork sees the same system prompt, tools, model, and message history as the main session, so you can hand it a side task without re-explaining the situation. The fork's own tool calls still stay out of your conversation and only its final result comes back, so your main context window stays clean. Use a fork when a named subagent would need too much background to be useful, or when you want to try several approaches in parallel from the same starting point.

773 

774Enabling fork mode changes Claude Code in three ways:

775 

776* Claude spawns a fork whenever it would otherwise use the [general-purpose](#built-in-subagents) subagent. Named subagents such as Explore still spawn as before.

777* Every subagent spawn runs in the [background](#run-subagents-in-foreground-or-background), whether it is a fork or a named subagent. Set `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` to `1` to keep spawns synchronous.

778* The `/fork` command spawns a fork instead of acting as an alias for [`/branch`](/en/commands).

779 

780You can start a fork yourself with `/fork` followed by a directive. Claude Code names the fork from the first words of the directive. The following example forks the conversation to draft test cases while you continue with the implementation in the main session:

781 

782```text theme={null}

783/fork draft unit tests for the parser changes so far

784```

785 

786The fork appears in a panel below your prompt and runs in the background while you keep working. When it finishes, its result arrives as a message in your main conversation. The next section covers the panel controls for watching and steering forks while they run.

787 

788### Observe and steer running forks

789 

790Running forks appear in a panel below the prompt input, with one row for the main session and one for each fork. Use these keys to interact with the panel:

791 

792| Key | Action |

793| :-------- | :----------------------------------------------------------------- |

794| `↑` / `↓` | Move between rows |

795| `Enter` | Open the selected fork's transcript and send it follow-up messages |

796| `x` | Dismiss a finished fork or stop a running one |

797| `Esc` | Return focus to the prompt input |

798 

799### How forks differ from named subagents

800 

801A fork inherits everything the main session has at the moment it spawns. A named subagent starts from its own definition.

802 

803| | Fork | Named subagent |

804| :---------------------- | :------------------------------- | :----------------------------------------------------------------------------------------- |

805| Context | Full conversation history | Fresh context with the prompt you pass |

806| System prompt and tools | Same as main session | From the subagent's [definition file](#write-subagent-files) |

807| Model | Same as main session | From the subagent's `model` field |

808| Permissions | Prompts surface in your terminal | [Pre-approved](#run-subagents-in-foreground-or-background) before launch, then auto-denied |

809| Prompt cache | Shared with main session | Separate cache |

810 

811Because a fork's system prompt and tool definitions are identical to the parent, its first request reuses the parent's prompt cache. This makes forking cheaper than spawning a fresh subagent for tasks that need the same context.

812 

813When Claude spawns a fork through the Agent tool, it can pass `isolation: "worktree"` so the fork's file edits are written to a separate git worktree instead of your checkout.

814 

815### Limitations

816 

817Fork mode works only in interactive sessions. It is disabled in [non-interactive mode](/en/headless), which includes the Agent SDK. A fork cannot spawn further forks.

818 

544## Example subagents819## Example subagents

545 820 

546These examples demonstrate effective patterns for building subagents. Use them as starting points, or generate a customized version with Claude.821These examples demonstrate effective patterns for building subagents. Use them as starting points, or generate a customized version with Claude.

terminal-config.md +241 −47

Details

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> 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.3> Use this file to discover all available pages before exploring further.

4 4 

5# Optimize your terminal setup5# Configure your terminal for Claude Code

6 6 

7> Claude Code works best when your terminal is properly configured. Follow these guidelines to optimize your experience.7> Fix Shift+Enter for newlines, get a terminal bell when Claude finishes, configure tmux, match the color theme, and enable Vim mode in the Claude Code CLI.

8 8 

9### Themes and appearance9Claude Code works in any terminal without configuration. This page is for when something specific is not behaving the way you expect. Find your symptom below. If everything already feels right, you do not need this page.

10 10 

11Claude cannot control the theme of your terminal. That's handled by your terminal application. You can match Claude Code's theme to your terminal any time via the `/config` command.11* [Shift+Enter submits instead of inserting a newline](#enter-multiline-prompts)

12* [Option-key shortcuts do nothing on macOS](#enable-option-key-shortcuts-on-macos)

13* [No sound or alert when Claude finishes](#get-a-terminal-bell-or-notification)

14* [You run Claude Code inside tmux](#configure-tmux)

15* [Display flickers or scrollback jumps](#switch-to-fullscreen-rendering)

16* [You want Vim keys in the prompt](#edit-prompts-with-vim-keybindings)

12 17 

13For additional customization of the Claude Code interface itself, you can configure a [custom status line](/en/statusline) to display contextual information like the current model, working directory, or git branch at the bottom of your terminal.18This page is about getting your terminal to send the right signals to Claude Code. To change which keys Claude Code itself responds to, see [keybindings](/en/keybindings) instead.

14 19 

15### Line breaks20## Enter multiline prompts

16 21 

17You have several options for entering line breaks into Claude Code:22Pressing Enter submits your message. To add a line break without submitting, press Ctrl+J, or type `\` and then press Enter. Both work in every terminal with no setup.

18 23 

19* **Quick escape**: Type `\` followed by Enter to create a newline24In most terminals you can also press Shift+Enter, but support varies by terminal emulator:

20* **Shift+Enter**: Works out of the box in iTerm2, WezTerm, Ghostty, and Kitty

21* **Keyboard shortcut**: Set up a keybinding to insert a newline in other terminals

22 25 

23**Set up Shift+Enter for other terminals**26| Terminal | Shift+Enter for newline |

27| :---------------------------------------------------------------------------------- | :------------------------------------------ |

28| Ghostty, Kitty, iTerm2, WezTerm, Warp, Apple Terminal | Works without setup |

29| VS Code, Cursor, Windsurf, Alacritty, Zed | Run `/terminal-setup` once |

30| Windows Terminal, gnome-terminal, JetBrains IDEs such as PyCharm and Android Studio | Not available; use Ctrl+J or `\` then Enter |

24 31 

25Run `/terminal-setup` within Claude Code to automatically configure Shift+Enter for VS Code, Alacritty, Zed, and Warp.32For VS Code, Cursor, Windsurf, Alacritty, and Zed, `/terminal-setup` writes Shift+Enter and other keybindings into the terminal's configuration file. In VS Code, Cursor, and Windsurf it also sets `terminal.integrated.mouseWheelScrollSensitivity` in the editor settings for smoother scrolling in [fullscreen mode](/en/fullscreen). Existing bindings and settings are left in place; if you see a message such as `VSCode terminal Shift+Enter key binding already configured`, no change was made. Run `/terminal-setup` directly in the host terminal rather than inside tmux or screen, since it needs to write to the host terminal's configuration.

33 

34If you are running inside tmux, Shift+Enter also requires the [tmux configuration below](#configure-tmux) even when the outer terminal supports it.

35 

36To bind newline to a different key, or to swap behavior so Enter inserts a newline and Shift+Enter submits, map the `chat:newline` and `chat:submit` actions in your [keybindings file](/en/keybindings).

37 

38## Enable Option key shortcuts on macOS

39 

40Some Claude Code shortcuts use the Option key, such as Option+Enter for a newline or Option+P to switch models. On macOS, most terminals do not send Option as a modifier by default, so these shortcuts do nothing until you enable it. The terminal setting for this is usually labeled "Use Option as Meta Key"; Meta is the historical Unix name for the key now labeled Option or Alt.

41 

42<Tabs>

43 <Tab title="Apple Terminal">

44 Open Settings → Profiles → Keyboard and check "Use Option as Meta Key".

45 

46 If you accepted Claude Code's first-run prompt that offered "Option+Enter for newlines and visual bell", this is already done. That prompt runs `/terminal-setup` for you, which enables Option as Meta and switches the audio bell to a visual screen flash in your Apple Terminal profile.

47 </Tab>

48 

49 <Tab title="iTerm2">

50 Open Settings → Profiles → Keys → General and set Left Option key and Right Option key to "Esc+".

51 </Tab>

52 

53 <Tab title="VS Code">

54 Add `"terminal.integrated.macOptionIsMeta": true` to your VS Code settings.

55 </Tab>

56</Tabs>

57 

58For Ghostty, Kitty, and other terminals, look for an Option-as-Alt or Option-as-Meta setting in the terminal's configuration file.

59 

60## Get a terminal bell or notification

61 

62When Claude finishes a task or pauses for a permission prompt, it fires a notification event. Surfacing this as a terminal bell or desktop notification lets you switch to other work while a long task runs.

63 

64Claude Code sends a desktop notification only in Ghostty, Kitty, and iTerm2; every other terminal needs a [Notification hook](#play-a-sound-with-a-notification-hook) instead. The notification also reaches your local machine over SSH, so a remote session can still alert you. Ghostty and Kitty forward it to your OS notification center without further setup. iTerm2 requires you to enable forwarding:

65 

66<Steps>

67 <Step title="Open iTerm2 notification settings">

68 Go to Settings → Profiles → Terminal.

69 </Step>

70 

71 <Step title="Enable alerts">

72 Check "Notification Center Alerts", then click "Filter Alerts" and enable "Send escape sequence-generated alerts".

73 </Step>

74</Steps>

75 

76If notifications still do not appear, confirm that your terminal application has notification permission in your OS settings, and if you are running inside tmux, [enable passthrough](#configure-tmux).

77 

78### Play a sound with a Notification hook

79 

80In any terminal you can configure a [Notification hook](/en/hooks-guide#get-notified-when-claude-needs-input) to play a sound or run a custom command when Claude needs your attention. Hooks run alongside the desktop notification rather than replacing it. Terminals such as Warp or Apple Terminal rely on a hook alone since Claude Code does not send them a desktop notification.

81 

82The example below plays a system sound on macOS. The linked guide has desktop notification commands for macOS, Linux, and Windows.

83 

84```json ~/.claude/settings.json theme={null}

85{

86 "hooks": {

87 "Notification": [

88 {

89 "hooks": [{ "type": "command", "command": "afplay /System/Library/Sounds/Glass.aiff" }]

90 }

91 ]

92 }

93}

94```

95 

96## Configure tmux

97 

98When Claude Code runs inside tmux, two things break by default: Shift+Enter submits instead of inserting a newline, and desktop notifications and the [progress bar](/en/settings#available-settings) never reach the outer terminal. Add these lines to `~/.tmux.conf`, then run `tmux source-file ~/.tmux.conf` to apply them to the running server:

99 

100```bash ~/.tmux.conf theme={null}

101set -g allow-passthrough on

102set -s extended-keys on

103set -as terminal-features 'xterm*:extkeys'

104```

105 

106The `allow-passthrough` line lets notifications and progress updates reach iTerm2, Ghostty, or Kitty instead of being swallowed by tmux. The `extended-keys` lines let tmux distinguish Shift+Enter from plain Enter so the newline shortcut works.

107 

108## Match the color theme

109 

110Use the `/theme` command, or the theme picker in `/config`, to choose a Claude Code theme that matches your terminal. Selecting the auto option detects your terminal's light or dark background, so the theme follows OS appearance changes whenever your terminal does. Claude Code does not control the terminal's own color scheme, which is set by the terminal application.

111 

112To customize what appears at the bottom of the interface, configure a [custom status line](/en/statusline) that shows the current model, working directory, git branch, or other context.

113 

114### Create a custom theme

26 115 

27<Note>116<Note>

28 The `/terminal-setup` command is only visible in terminals that require manual configuration. If you're using iTerm2, WezTerm, Ghostty, or Kitty, you won't see this command because Shift+Enter already works natively.117 Custom themes require Claude Code v2.1.118 or later.

29</Note>118</Note>

30 119 

31**Set up Option+Enter (VS Code, iTerm2 or macOS Terminal.app)**120In addition to the built-in presets, `/theme` lists any custom themes you have defined and any themes contributed by installed [plugins](/en/plugins-reference#themes). Select **New custom theme…** at the end of the list to create one interactively: you name the theme, then pick individual color tokens to override. Press `Ctrl+E` while a custom theme is highlighted to edit it.

121 

122Each custom theme is a JSON file in `~/.claude/themes/`. The filename without the `.json` extension is the theme's slug, and selecting the theme stores `custom:<slug>` as your theme preference. The file has three optional fields:

123 

124| Field | Type | Description |

125| :---------- | :----- | :---------------------------------------------------------------------------------------------------------------------------------------------- |

126| `name` | string | Display label shown in `/theme`. Defaults to the filename slug |

127| `base` | string | Built-in preset the theme starts from: `dark`, `light`, `dark-daltonized`, `light-daltonized`, `dark-ansi`, or `light-ansi`. Defaults to `dark` |

128| `overrides` | object | Map of color token names to color values. Tokens not listed here fall through to the base preset |

129 

130Color values accept `#rrggbb`, `#rgb`, `rgb(r,g,b)`, `ansi256(n)`, or `ansi:<name>` where `<name>` is one of the 16 standard ANSI color names such as `red` or `cyanBright`. Unknown tokens and invalid color values are ignored, so a typo cannot break rendering.

131 

132The following example defines a theme that keeps the dark preset but recolors the prompt accent, error text, and success text:

133 

134```json ~/.claude/themes/dracula.json theme={null}

135{

136 "name": "Dracula",

137 "base": "dark",

138 "overrides": {

139 "claude": "#bd93f9",

140 "error": "#ff5555",

141 "success": "#50fa7b"

142 }

143}

144```

145 

146Claude Code watches `~/.claude/themes/` and reloads when a file changes, so edits made in your editor apply to a running session without a restart.

147 

148Below is the full list of customizations you can set in `overrides`. The interactive editor in `/theme` shows the same tokens with a live preview, including a small number of internal tokens not covered here.

149 

150<Accordion title="Color token reference">

151 The following example combines tokens from several of the groups below: the brand accent, the plan mode border, the diff backgrounds, and the fullscreen message background.

152 

153 ```json ~/.claude/themes/midnight.json theme={null}

154 {

155 "name": "Midnight",

156 "base": "dark",

157 "overrides": {

158 "claude": "#a78bfa",

159 "planMode": "#38bdf8",

160 "diffAdded": "#14532d",

161 "diffRemoved": "#7f1d1d",

162 "userMessageBackground": "#1e1b4b"

163 }

164 }

165 ```

166 

167 #### Text and accent colors

168 

169 Control the primary brand accent and the foreground text shades used throughout the interface.

170 

171 | Token | Controls |

172 | :------------ | :--------------------------------------------------------------- |

173 | `claude` | Primary brand accent, used for the spinner and assistant label |

174 | `text` | Default foreground text |

175 | `inverseText` | Text drawn on top of a colored background, such as status badges |

176 | `inactive` | Secondary text such as hints, timestamps, and disabled items |

177 | `subtle` | Faint borders and de-emphasized secondary text |

178 | `permission` | Dialog borders, including permission prompts and pickers |

179 | `remember` | Memory and `CLAUDE.md` indicators |

180 

181 #### Status colors

182 

183 Signal success, failure, and warning states across messages and indicators.

184 

185 | Token | Controls |

186 | :-------- | :--------------------------------------------------- |

187 | `success` | Success messages and passing checks |

188 | `error` | Error messages and failures |

189 | `warning` | Warnings, caution messages, and the auto mode border |

190 | `merged` | Merged pull request status |

191 

192 #### Input box and mode indicators

193 

194 Set the input box border color and the accent shown while a permission mode or indicator is active.

195 

196 | Token | Controls |

197 | :------------- | :------------------------------------------------- |

198 | `promptBorder` | Input box border in the default permission mode |

199 | `planMode` | Plan mode accent and border |

200 | `autoAccept` | Accept-edits mode accent and border |

201 | `bashBorder` | Input box border when entering a `!` shell command |

202 | `ide` | IDE connection indicator |

203 | `fastMode` | Fast mode indicator |

204 

205 #### Diff rendering

206 

207 Color added and removed code in file edits and reviews.

208 

209 | Token | Controls |

210 | :------------------ | :------------------------------------------------- |

211 | `diffAdded` | Background of added lines |

212 | `diffRemoved` | Background of removed lines |

213 | `diffAddedDimmed` | Background of unchanged context near added lines |

214 | `diffRemovedDimmed` | Background of unchanged context near removed lines |

215 | `diffAddedWord` | Word-level highlight within an added line |

216 | `diffRemovedWord` | Word-level highlight within a removed line |

217 

218 #### Fullscreen mode

32 219 

33**For Mac Terminal.app:**220 Apply only in [fullscreen rendering mode](/en/fullscreen), where messages have a background fill.

34 221 

351. Open Settings → Profiles Keyboard222 | Token | Controls |

362. Check "Use Option as Meta Key"223 | :---------------------- | :------------------------------------------------ |

224 | `userMessageBackground` | Background behind your messages in the transcript |

225 | `selectionBg` | Background of text selected with the mouse |

37 226 

38**For iTerm2 and VS Code terminal:**227 #### Shimmer variants and subagent colors

39 228 

401. Open Settings Profiles Keys229 Several tokens have a paired `Shimmer` variant, such as `claudeShimmer` and `warningShimmer`, that supplies the lighter color used in the spinner's animated gradient. Override the shimmer alongside its base token if the animation looks mismatched.

412. Under General, set Left/Right Option key to "Esc+"

42 230 

43### Notification setup231 Each [subagent](/en/sub-agents) and parallel task is shown in one of eight named colors so you can tell them apart in the transcript. The token names follow the pattern `<color>_FOR_SUBAGENTS_ONLY`, where `<color>` is `red`, `blue`, `green`, `yellow`, `purple`, `orange`, `pink`, or `cyan`. Override these to change what each named color looks like. For example, a subagent with `color: blue` in its definition is drawn using the `blue_FOR_SUBAGENTS_ONLY` value.

232</Accordion>

44 233 

45Never miss when Claude completes a task with proper notification configuration:234## Switch to fullscreen rendering

46 235 

47#### iTerm 2 system notifications236If the display flickers or the scroll position jumps while Claude is working, switch to [fullscreen rendering mode](/en/fullscreen). It draws to a separate screen the terminal reserves for full-screen apps instead of appending to your normal scrollback, which keeps memory usage flat and adds mouse support for scrolling and selection. In this mode you scroll with the mouse or PageUp inside Claude Code rather than with your terminal's native scrollback; see the [fullscreen page](/en/fullscreen#search-and-review-the-conversation) for how to search and copy.

48 237 

49For iTerm 2 alerts when tasks complete:238Run `/tui fullscreen` to switch in the current session with your conversation intact. To make it the default, set the `CLAUDE_CODE_NO_FLICKER` environment variable before starting Claude Code:

50 239 

511. Open iTerm 2 Preferences240<CodeGroup>

522. Navigate to Profiles Terminal241 ```bash Bash and Zsh theme={null}

533. Enable "Silence bell" and Filter Alerts → "Send escape sequence-generated alerts"242 CLAUDE_CODE_NO_FLICKER=1 claude

544. Set your preferred notification delay243 ```

55 244 

56Note that these notifications are specific to iTerm 2 and not available in the default macOS Terminal.245 ```powershell PowerShell theme={null}

246 $env:CLAUDE_CODE_NO_FLICKER = "1"; claude

247 ```

57 248 

58#### Custom notification hooks249 ```json ~/.claude/settings.json theme={null}

250 {

251 "env": {

252 "CLAUDE_CODE_NO_FLICKER": "1"

253 }

254 }

255 ```

256</CodeGroup>

59 257 

60For advanced notification handling, you can create [notification hooks](/en/hooks#notification) to run your own logic.258## Paste large content

61 259 

62### Handling large inputs260When you paste more than 10,000 characters into the prompt, Claude Code collapses the input to a `[Pasted text]` placeholder so the input box stays usable. The full content is still sent to Claude when you submit.

63 261 

64When working with extensive code or long instructions:262The VS Code integrated terminal can drop characters from very large pastes before they reach Claude Code, so prefer file-based workflows there. For very large inputs such as entire files or long logs, write the content to a file and ask Claude to read it instead of pasting. This keeps the conversation transcript readable and lets Claude reference the file by path in later turns.

65 263 

66* **Avoid direct pasting**: Claude Code may struggle with very long pasted content264## Edit prompts with Vim keybindings

67* **Use file-based workflows**: Write content to a file and ask Claude to read it

68* **Be aware of VS Code limitations**: The VS Code terminal is particularly prone to truncating long pastes

69 265 

70### Vim Mode266Claude Code includes a Vim-style editing mode for the prompt input. Enable it through `/config` → Editor mode, or by setting [`editorMode`](/en/settings#available-settings) to `"vim"` in `~/.claude/settings.json`. Set Editor mode back to `normal` to turn it off.

71 267 

72Claude Code supports a subset of Vim keybindings that can be enabled with `/vim` or configured via `/config`.268Vim mode supports a subset of NORMAL- and VISUAL-mode motions and operators, such as `hjkl` navigation, `v`/`V` selection, and `d`/`c`/`y` with text objects. See the [Vim editor mode reference](/en/interactive-mode#vim-editor-mode) for the full key table. Vim motions are not remappable through the keybindings file.

73 269 

74The supported subset includes:270Pressing Enter still submits your prompt in INSERT mode, unlike standard Vim. Use `o` or `O` in NORMAL mode, or Ctrl+J, to insert a newline instead.

75 271 

76* Mode switching: `Esc` (to NORMAL), `i`/`I`, `a`/`A`, `o`/`O` (to INSERT)272## Related resources

77* Navigation: `h`/`j`/`k`/`l`, `w`/`e`/`b`, `0`/`$`/`^`, `gg`/`G`, `f`/`F`/`t`/`T` with `;`/`,` repeat

78* Editing: `x`, `dw`/`de`/`db`/`dd`/`D`, `cw`/`ce`/`cb`/`cc`/`C`, `.` (repeat)

79* Yank/paste: `yy`/`Y`, `yw`/`ye`/`yb`, `p`/`P`

80* Text objects: `iw`/`aw`, `iW`/`aW`, `i"`/`a"`, `i'`/`a'`, `i(`/`a(`, `i[`/`a[`, `i{`/`a{`

81* Indentation: `>>`/`<<`

82* Line operations: `J` (join lines)

83 273 

84See [Interactive mode](/en/interactive-mode#vim-editor-mode) for the complete reference.274* [Interactive mode](/en/interactive-mode): full keyboard shortcut reference and the Vim key table

275* [Keybindings](/en/keybindings): remap any Claude Code shortcut, including Enter and Shift+Enter

276* [Fullscreen rendering](/en/fullscreen): details on scrolling, search, and copy in fullscreen mode

277* [Hooks guide](/en/hooks-guide): more Notification hook examples for Linux and Windows

278* [Troubleshooting](/en/troubleshooting): fixes for issues outside terminal configuration

Details

6 6 

7> Learn how Claude Code can integrate with various third-party services and infrastructure to meet enterprise deployment requirements.7> Learn how Claude Code can integrate with various third-party services and infrastructure to meet enterprise deployment requirements.

8 8 

9 

10 

9Organizations can deploy Claude Code through Anthropic directly or through a cloud provider. This page helps you choose the right configuration.11Organizations can deploy Claude Code through Anthropic directly or through a cloud provider. This page helps you choose the right configuration.

10 12 

13<Experiment flag="docs-contact-sales-cta" treatment={<ContactSalesCard surface="third_party_overview" />} />

14 

11## Compare deployment options15## Compare deployment options

12 16 

13For most organizations, Claude for Teams or Claude for Enterprise provides the best experience. Team members get access to both Claude Code and Claude on the web with a single subscription, centralized billing, and no infrastructure setup required.17For most organizations, Claude for Teams or Claude for Enterprise provides the best experience. Team members get access to both Claude Code and Claude on the web with a single subscription, centralized billing, and no infrastructure setup required.


44 48 

45 <tr>49 <tr>

46 <td>Billing</td>50 <td>Billing</td>

47 <td><strong>Teams:</strong> \$150/seat (Premium) with PAYG available<br /><strong>Enterprise:</strong> <a href="https://claude.com/contact-sales">Contact Sales</a></td>51 <td><strong>Teams:</strong> \$150/seat (Premium) with PAYG available<br /><strong>Enterprise:</strong> <a href="https://claude.com/contact-sales?utm_source=claude_code&utm_medium=docs&utm_content=third_party_enterprise">Contact Sales</a></td>

48 <td>PAYG</td>52 <td>PAYG</td>

49 <td>PAYG through AWS</td>53 <td>PAYG through AWS</td>

50 <td>PAYG through GCP</td>54 <td>PAYG through GCP</td>


109 113 

110Select a deployment option to view setup instructions:114Select a deployment option to view setup instructions:

111 115 

112* [Claude for Teams or Enterprise](/en/iam#claude-for-teams-or-enterprise-recommended)116* [Claude for Teams or Enterprise](/en/authentication#claude-for-teams-or-enterprise)

113* [Anthropic Console](/en/iam#claude-console-authentication)117* [Anthropic Console](/en/authentication#claude-console-authentication)

114* [Amazon Bedrock](/en/amazon-bedrock)118* [Amazon Bedrock](/en/amazon-bedrock)

115* [Google Vertex AI](/en/google-vertex-ai)119* [Google Vertex AI](/en/google-vertex-ai)

116* [Microsoft Foundry](/en/microsoft-foundry)120* [Microsoft Foundry](/en/microsoft-foundry)


128 132 

129<Tabs>133<Tabs>

130 <Tab title="Corporate proxy">134 <Tab title="Corporate proxy">

131 Route Bedrock traffic through your corporate proxy by setting the following [environment variables](/en/settings#environment-variables):135 Route Bedrock traffic through your corporate proxy by setting the following [environment variables](/en/env-vars):

132 136 

133 ```bash theme={null}137 ```bash theme={null}

134 # Enable Bedrock138 # Enable Bedrock


141 </Tab>145 </Tab>

142 146 

143 <Tab title="LLM Gateway">147 <Tab title="LLM Gateway">

144 Route Bedrock traffic through your LLM gateway by setting the following [environment variables](/en/settings#environment-variables):148 Route Bedrock traffic through your LLM gateway by setting the following [environment variables](/en/env-vars):

145 149 

146 ```bash theme={null}150 ```bash theme={null}

147 # Enable Bedrock151 # Enable Bedrock


158 162 

159<Tabs>163<Tabs>

160 <Tab title="Corporate proxy">164 <Tab title="Corporate proxy">

161 Route Foundry traffic through your corporate proxy by setting the following [environment variables](/en/settings#environment-variables):165 Route Foundry traffic through your corporate proxy by setting the following [environment variables](/en/env-vars):

162 166 

163 ```bash theme={null}167 ```bash theme={null}

164 # Enable Microsoft Foundry168 # Enable Microsoft Foundry


172 </Tab>176 </Tab>

173 177 

174 <Tab title="LLM Gateway">178 <Tab title="LLM Gateway">

175 Route Foundry traffic through your LLM gateway by setting the following [environment variables](/en/settings#environment-variables):179 Route Foundry traffic through your LLM gateway by setting the following [environment variables](/en/env-vars):

176 180 

177 ```bash theme={null}181 ```bash theme={null}

178 # Enable Microsoft Foundry182 # Enable Microsoft Foundry


189 193 

190<Tabs>194<Tabs>

191 <Tab title="Corporate proxy">195 <Tab title="Corporate proxy">

192 Route Vertex AI traffic through your corporate proxy by setting the following [environment variables](/en/settings#environment-variables):196 Route Vertex AI traffic through your corporate proxy by setting the following [environment variables](/en/env-vars):

193 197 

194 ```bash theme={null}198 ```bash theme={null}

195 # Enable Vertex199 # Enable Vertex


203 </Tab>207 </Tab>

204 208 

205 <Tab title="LLM Gateway">209 <Tab title="LLM Gateway">

206 Route Vertex AI traffic through your LLM gateway by setting the following [environment variables](/en/settings#environment-variables):210 Route Vertex AI traffic through your LLM gateway by setting the following [environment variables](/en/env-vars):

207 211 

208 ```bash theme={null}212 ```bash theme={null}

209 # Enable Vertex213 # Enable Vertex


239 243 

240Encourage new users to try Claude Code for codebase Q\&A, or on smaller bug fixes or feature requests. Ask Claude Code to make a plan. Check Claude's suggestions and give feedback if it's off-track. Over time, as users understand this new paradigm better, then they'll be more effective at letting Claude Code run more agentically.244Encourage new users to try Claude Code for codebase Q\&A, or on smaller bug fixes or feature requests. Ask Claude Code to make a plan. Check Claude's suggestions and give feedback if it's off-track. Over time, as users understand this new paradigm better, then they'll be more effective at letting Claude Code run more agentically.

241 245 

246### Pin model versions for cloud providers

247 

248If you deploy through [Bedrock](/en/amazon-bedrock), [Vertex AI](/en/google-vertex-ai), or [Foundry](/en/microsoft-foundry), pin specific model versions using `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, and `ANTHROPIC_DEFAULT_HAIKU_MODEL`. Without pinning, model aliases resolve to the latest version, which may not yet be enabled in your account when Anthropic releases an update. Pinning lets you control when your users move to a new model. See [Model configuration](/en/model-config#pin-models-for-third-party-deployments) for what each provider does when the latest version is unavailable.

249 

242### Configure security policies250### Configure security policies

243 251 

244Security teams can configure managed permissions for what Claude Code is and is not allowed to do, which cannot be overwritten by local configuration. [Learn more](/en/security).252Security teams can configure managed permissions for what Claude Code is and is not allowed to do, which cannot be overwritten by local configuration. [Learn more](/en/security).

tools-reference.md +149 −0 added

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# Tools reference

6 

7> Complete reference for the tools Claude Code can use, including permission requirements.

8 

9Claude Code has access to a set of built-in tools that help it understand and modify your codebase. The tool names are the exact strings you use in [permission rules](/en/permissions#tool-specific-permission-rules), [subagent tool lists](/en/sub-agents), and [hook matchers](/en/hooks). To disable a tool entirely, add its name to the `deny` array in your [permission settings](/en/permissions#tool-specific-permission-rules).

10 

11To add custom tools, connect an [MCP server](/en/mcp). To extend Claude with reusable prompt-based workflows, write a [skill](/en/skills), which runs through the existing `Skill` tool rather than adding a new tool entry.

12 

13| Tool | Description | Permission Required |

14| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------ |

15| `Agent` | Spawns a [subagent](/en/sub-agents) with its own context window to handle a task | No |

16| `AskUserQuestion` | Asks multiple-choice questions to gather requirements or clarify ambiguity | No |

17| `Bash` | Executes shell commands in your environment. See [Bash tool behavior](#bash-tool-behavior) | Yes |

18| `CronCreate` | Schedules a recurring or one-shot prompt within the current session. Tasks are session-scoped and restored on `--resume` or `--continue` if unexpired. See [scheduled tasks](/en/scheduled-tasks) | No |

19| `CronDelete` | Cancels a scheduled task by ID | No |

20| `CronList` | Lists all scheduled tasks in the session | No |

21| `Edit` | Makes targeted edits to specific files | Yes |

22| `EnterPlanMode` | Switches to plan mode to design an approach before coding | No |

23| `EnterWorktree` | Creates an isolated [git worktree](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees) and switches into it. Pass a `path` to switch into an existing worktree of the current repository instead of creating a new one. Not available to subagents | No |

24| `ExitPlanMode` | Presents a plan for approval and exits plan mode | Yes |

25| `ExitWorktree` | Exits a worktree session and returns to the original directory. Not available to subagents | No |

26| `Glob` | Finds files based on pattern matching | No |

27| `Grep` | Searches for patterns in file contents | No |

28| `ListMcpResourcesTool` | Lists resources exposed by connected [MCP servers](/en/mcp) | No |

29| `LSP` | Code intelligence via language servers: jump to definitions, find references, report type errors and warnings. See [LSP tool behavior](#lsp-tool-behavior) | No |

30| `Monitor` | Runs a command in the background and feeds each output line back to Claude, so it can react to log entries, file changes, or polled status mid-conversation. See [Monitor tool](#monitor-tool) | Yes |

31| `NotebookEdit` | Modifies Jupyter notebook cells | Yes |

32| `PowerShell` | Executes PowerShell commands natively. See [PowerShell tool](#powershell-tool) for availability | Yes |

33| `Read` | Reads the contents of files | No |

34| `ReadMcpResourceTool` | Reads a specific MCP resource by URI | No |

35| `SendMessage` | Sends a message to an [agent team](/en/agent-teams) teammate, or [resumes a subagent](/en/sub-agents#resume-subagents) by its agent ID. Stopped subagents auto-resume in the background. Only available when `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` is set | No |

36| `Skill` | Executes a [skill](/en/skills#control-who-invokes-a-skill) within the main conversation | Yes |

37| `TaskCreate` | Creates a new task in the task list | No |

38| `TaskGet` | Retrieves full details for a specific task | No |

39| `TaskList` | Lists all tasks with their current status | No |

40| `TaskOutput` | (Deprecated) Retrieves output from a background task. Prefer `Read` on the task's output file path | No |

41| `TaskStop` | Kills a running background task by ID | No |

42| `TaskUpdate` | Updates task status, dependencies, details, or deletes tasks | No |

43| `TeamCreate` | Creates an [agent team](/en/agent-teams) with multiple teammates. Only available when `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` is set | No |

44| `TeamDelete` | Disbands an agent team and cleans up teammate processes. Only available when `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` is set | No |

45| `TodoWrite` | Manages the session task checklist. Available in non-interactive mode and the [Agent SDK](/en/headless); interactive sessions use TaskCreate, TaskGet, TaskList, and TaskUpdate instead | No |

46| `ToolSearch` | Searches for and loads deferred tools when [tool search](/en/mcp#scale-with-mcp-tool-search) is enabled | No |

47| `WebFetch` | Fetches content from a specified URL | Yes |

48| `WebSearch` | Performs web searches | Yes |

49| `Write` | Creates or overwrites files | Yes |

50 

51Permission rules can be configured using `/permissions` or in [permission settings](/en/settings#available-settings). Also see [Tool-specific permission rules](/en/permissions#tool-specific-permission-rules).

52 

53## Bash tool behavior

54 

55The Bash tool runs each command in a separate process with the following persistence behavior:

56 

57* When Claude runs `cd` in the main session, the new working directory carries over to later Bash commands as long as it stays inside the project directory or an [additional working directory](/en/permissions#working-directories) you added with `--add-dir`, `/add-dir`, or `additionalDirectories` in settings. Subagent sessions never carry over working directory changes.

58 * If `cd` lands outside those directories, Claude Code resets to the project directory and appends `Shell cwd was reset to <dir>` to the tool result.

59 * To disable this carry-over so every Bash command starts in the project directory, set `CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR=1`.

60* Environment variables do not persist. An `export` in one command will not be available in the next.

61 

62Activate your virtualenv or conda environment before launching Claude Code. To make environment variables persist across Bash commands, set [`CLAUDE_ENV_FILE`](/en/env-vars) to a shell script before launching Claude Code, or use a [SessionStart hook](/en/hooks#persist-environment-variables) to populate it dynamically.

63 

64## LSP tool behavior

65 

66The LSP tool gives Claude code intelligence from a running language server. After each file edit, it automatically reports type errors and warnings so Claude can fix issues without a separate build step. Claude can also call it directly to navigate code:

67 

68* Jump to a symbol's definition

69* Find all references to a symbol

70* Get type information at a position

71* List symbols in a file or workspace

72* Find implementations of an interface

73* Trace call hierarchies

74 

75The tool is inactive until you install a [code intelligence plugin](/en/discover-plugins#code-intelligence) for your language. The plugin bundles the language server configuration, and you install the server binary separately.

76 

77## Monitor tool

78 

79<Note>

80 The Monitor tool requires Claude Code v2.1.98 or later.

81</Note>

82 

83The Monitor tool lets Claude watch something in the background and react when it changes, without pausing the conversation. Ask Claude to:

84 

85* Tail a log file and flag errors as they appear

86* Poll a PR or CI job and report when its status changes

87* Watch a directory for file changes

88* Track output from any long-running script you point it at

89 

90Claude writes a small script for the watch, runs it in the background, and receives each output line as it arrives. You keep working in the same session and Claude interjects when an event lands. Stop a monitor by asking Claude to cancel it or by ending the session.

91 

92Monitor uses the same [permission rules as Bash](/en/permissions#tool-specific-permission-rules), so `allow` and `deny` patterns you have set for Bash apply here too. It is not available on Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. It is also not available when `DISABLE_TELEMETRY` or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` is set.

93 

94Plugins can declare monitors that start automatically when the plugin is active, instead of asking Claude to start them. See [plugin monitors](/en/plugins-reference#monitors).

95 

96## PowerShell tool

97 

98The PowerShell tool lets Claude run PowerShell commands natively. On Windows, this means commands run in PowerShell instead of routing through Git Bash. The tool is rolling out progressively on Windows and is opt-in on Linux, macOS, and WSL.

99 

100### Enable the PowerShell tool

101 

102Set `CLAUDE_CODE_USE_POWERSHELL_TOOL=1` in your environment or in `settings.json`:

103 

104```json theme={null}

105{

106 "env": {

107 "CLAUDE_CODE_USE_POWERSHELL_TOOL": "1"

108 }

109}

110```

111 

112On Windows, set the variable to `0` to opt out of the rollout. On Linux, macOS, and WSL, the tool requires PowerShell 7 or later: install `pwsh` and ensure it is on your `PATH`.

113 

114On Windows, Claude Code auto-detects `pwsh.exe` for PowerShell 7+ with a fallback to `powershell.exe` for PowerShell 5.1. The Bash tool remains registered alongside the PowerShell tool, so you may need to ask Claude to use PowerShell.

115 

116### Shell selection in settings, hooks, and skills

117 

118Three additional settings control where PowerShell is used:

119 

120* `"defaultShell": "powershell"` in [`settings.json`](/en/settings#available-settings): routes interactive `!` commands through PowerShell. Requires the PowerShell tool to be enabled.

121* `"shell": "powershell"` on individual [command hooks](/en/hooks#command-hook-fields): runs that hook in PowerShell. Hooks spawn PowerShell directly, so this works regardless of `CLAUDE_CODE_USE_POWERSHELL_TOOL`.

122* `shell: powershell` in [skill frontmatter](/en/skills#frontmatter-reference): runs `` !`command` `` blocks in PowerShell. Requires the PowerShell tool to be enabled.

123 

124The same main-session working-directory reset behavior described under the Bash tool section applies to PowerShell commands, including the `CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR` environment variable.

125 

126### Preview limitations

127 

128The PowerShell tool has the following known limitations during the preview:

129 

130* PowerShell profiles are not loaded

131* On Windows, sandboxing is not supported

132* On Windows, Git Bash is still required to start Claude Code

133 

134## Check which tools are available

135 

136Your exact tool set depends on your provider, platform, and settings. To check what's loaded in a running session, ask Claude directly:

137 

138```text theme={null}

139What tools do you have access to?

140```

141 

142Claude gives a conversational summary. For exact MCP tool names, run `/mcp`.

143 

144## See also

145 

146* [MCP servers](/en/mcp): add custom tools by connecting external servers

147* [Permissions](/en/permissions): permission system, rule syntax, and tool-specific patterns

148* [Subagents](/en/sub-agents): configure tool access for subagents

149* [Hooks](/en/hooks-guide): run custom commands before or after tool execution

troubleshooting.md +676 −110

Details

6 6 

7> Discover solutions to common issues with Claude Code installation and usage.7> Discover solutions to common issues with Claude Code installation and usage.

8 8 

9## Troubleshoot installation issues

10 

11<Tip>

12 If you'd rather skip the terminal entirely, the [Claude Code Desktop app](/en/desktop-quickstart) lets you install and use Claude Code through a graphical interface. Download it for [macOS](https://claude.ai/api/desktop/darwin/universal/dmg/latest/redirect?utm_source=claude_code\&utm_medium=docs) or [Windows](https://claude.com/download?utm_source=claude_code\&utm_medium=docs) and start coding without any command-line setup.

13</Tip>

14 

15Find the error message or symptom you're seeing:

16 

17| What you see | Solution |

18| :-------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |

19| `command not found: claude` or `'claude' is not recognized` | [Fix your PATH](#command-not-found-claude-after-installation) |

20| `syntax error near unexpected token '<'` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) |

21| `curl: (56) Failure writing output to destination` | [Download script first, then run it](#curl-56-failure-writing-output-to-destination) |

22| `Killed` during install on Linux | [Add swap space for low-memory servers](#install-killed-on-low-memory-linux-servers) |

23| `TLS connect error` or `SSL/TLS secure channel` | [Update CA certificates](#tls-or-ssl-connection-errors) |

24| `Failed to fetch version` or can't reach download server | [Check network and proxy settings](#check-network-connectivity) |

25| `irm is not recognized` or `&& is not valid` | [Use the right command for your shell](#windows-wrong-install-command) |

26| `'bash' is not recognized as the name of a cmdlet` | [Use the Windows installer command](#windows-wrong-install-command) |

27| `Claude Code on Windows requires git-bash` | [Install or configure Git Bash](#windows-claude-code-on-windows-requires-git-bash) |

28| `Claude Code does not support 32-bit Windows` | [Open Windows PowerShell, not the x86 entry](#windows-claude-code-does-not-support-32-bit-windows) |

29| `Error loading shared library` | [Wrong binary variant for your system](#linux-wrong-binary-variant-installed-musl/glibc-mismatch) |

30| `Illegal instruction` on Linux | [Architecture mismatch](#illegal-instruction-on-linux) |

31| `dyld: cannot load`, `dyld: Symbol not found`, or `Abort trap` on macOS | [Binary incompatibility](#dyld-cannot-load-on-macos) |

32| `Invoke-Expression: Missing argument in parameter list` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) |

33| `App unavailable in region` | Claude Code is not available in your country. See [supported countries](https://www.anthropic.com/supported-countries). |

34| `unable to get local issuer certificate` | [Configure corporate CA certificates](#tls-or-ssl-connection-errors) |

35| `OAuth error` or `403 Forbidden` | [Fix authentication](#authentication-issues) |

36| `API Error: 500`, `529 Overloaded`, `429`, or other 4xx and 5xx errors not listed above | See the [Error reference](/en/errors) |

37 

38If your issue isn't listed, work through these diagnostic steps.

39 

40## Debug installation problems

41 

42### Check network connectivity

43 

44The installer downloads from `downloads.claude.ai`. Verify you can reach it:

45 

46```bash theme={null}

47curl -sI https://downloads.claude.ai

48```

49 

50If this fails, your network may be blocking the connection. Common causes:

51 

52* Corporate firewalls or proxies blocking `downloads.claude.ai`

53* Regional network restrictions: try a VPN or alternative network

54* TLS/SSL issues: update your system's CA certificates, or check if `HTTPS_PROXY` is configured

55 

56If you're behind a corporate proxy, set `HTTPS_PROXY` and `HTTP_PROXY` to your proxy's address before installing. Ask your IT team for the proxy URL if you don't know it, or check your browser's proxy settings.

57 

58This example sets both proxy variables, then runs the installer through your proxy:

59 

60```bash theme={null}

61export HTTP_PROXY=http://proxy.example.com:8080

62export HTTPS_PROXY=http://proxy.example.com:8080

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

64```

65 

66### Verify your PATH

67 

68If installation succeeded but you get a `command not found` or `not recognized` error when running `claude`, the install directory isn't in your PATH. Your shell searches for programs in directories listed in PATH, and the installer places `claude` at `~/.local/bin/claude` on macOS/Linux or `%USERPROFILE%\.local\bin\claude.exe` on Windows.

69 

70Check if the install directory is in your PATH by listing your PATH entries and filtering for `local/bin`:

71 

72<Tabs>

73 <Tab title="macOS/Linux">

74 ```bash theme={null}

75 echo $PATH | tr ':' '\n' | grep local/bin

76 ```

77 

78 If there's no output, the directory is missing. Add it to your shell configuration:

79 

80 ```bash theme={null}

81 # Zsh (macOS default)

82 echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc

83 source ~/.zshrc

84 

85 # Bash (Linux default)

86 echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc

87 source ~/.bashrc

88 ```

89 

90 Alternatively, close and reopen your terminal.

91 

92 Verify the fix worked:

93 

94 ```bash theme={null}

95 claude --version

96 ```

97 </Tab>

98 

99 <Tab title="Windows PowerShell">

100 ```powershell theme={null}

101 $env:PATH -split ';' | Select-String 'local\\bin'

102 ```

103 

104 If there's no output, add the install directory to your User PATH:

105 

106 ```powershell theme={null}

107 $currentPath = [Environment]::GetEnvironmentVariable('PATH', 'User')

108 [Environment]::SetEnvironmentVariable('PATH', "$currentPath;$env:USERPROFILE\.local\bin", 'User')

109 ```

110 

111 Restart your terminal for the change to take effect.

112 

113 Verify the fix worked:

114 

115 ```powershell theme={null}

116 claude --version

117 ```

118 </Tab>

119 

120 <Tab title="Windows CMD">

121 ```batch theme={null}

122 echo %PATH% | findstr /i "local\bin"

123 ```

124 

125 If there's no output, open System Settings, go to Environment Variables, and add `%USERPROFILE%\.local\bin` to your User PATH variable. Restart your terminal.

126 

127 Verify the fix worked:

128 

129 ```batch theme={null}

130 claude --version

131 ```

132 </Tab>

133</Tabs>

134 

135### Check for conflicting installations

136 

137Multiple Claude Code installations can cause version mismatches or unexpected behavior. Check what's installed:

138 

139<Tabs>

140 <Tab title="macOS/Linux">

141 List all `claude` binaries found in your PATH:

142 

143 ```bash theme={null}

144 which -a claude

145 ```

146 

147 Check whether the native installer and npm versions are present:

148 

149 ```bash theme={null}

150 ls -la ~/.local/bin/claude

151 ```

152 

153 ```bash theme={null}

154 ls -la ~/.claude/local/

155 ```

156 

157 ```bash theme={null}

158 npm -g ls @anthropic-ai/claude-code 2>/dev/null

159 ```

160 </Tab>

161 

162 <Tab title="Windows PowerShell">

163 ```powershell theme={null}

164 where.exe claude

165 Test-Path "$env:LOCALAPPDATA\Claude Code\claude.exe"

166 ```

167 </Tab>

168</Tabs>

169 

170If you find multiple installations, keep only one. The native install at `~/.local/bin/claude` is recommended. Remove any extra installations:

171 

172Uninstall an npm global install:

173 

174```bash theme={null}

175npm uninstall -g @anthropic-ai/claude-code

176```

177 

178Remove a Homebrew install on macOS (use `claude-code@latest` if you installed that cask):

179 

180```bash theme={null}

181brew uninstall --cask claude-code

182```

183 

184### Check directory permissions

185 

186The installer needs write access to `~/.local/bin/` and `~/.claude/`. If installation fails with permission errors, check whether these directories are writable:

187 

188```bash theme={null}

189test -w ~/.local/bin && echo "writable" || echo "not writable"

190test -w ~/.claude && echo "writable" || echo "not writable"

191```

192 

193If either directory isn't writable, create the install directory and set your user as the owner:

194 

195```bash theme={null}

196sudo mkdir -p ~/.local/bin

197sudo chown -R $(whoami) ~/.local

198```

199 

200### Verify the binary works

201 

202If `claude` is installed but crashes or hangs on startup, run these checks to narrow down the cause.

203 

204Confirm the binary exists and is executable:

205 

206```bash theme={null}

207ls -la $(which claude)

208```

209 

210On Linux, check for missing shared libraries. If `ldd` shows missing libraries, you may need to install system packages. On Alpine Linux and other musl-based distributions, see [Alpine Linux setup](/en/setup#alpine-linux-and-musl-based-distributions).

211 

212```bash theme={null}

213ldd $(which claude) | grep "not found"

214```

215 

216Run a quick sanity check that the binary can execute:

217 

218```bash theme={null}

219claude --version

220```

221 

9## Common installation issues222## Common installation issues

10 223 

224These are the most frequently encountered installation problems and their solutions.

225 

226### Install script returns HTML instead of a shell script

227 

228When running the install command, you may see one of these errors:

229 

230```text theme={null}

231bash: line 1: syntax error near unexpected token `<'

232bash: line 1: `<!DOCTYPE html>'

233```

234 

235On PowerShell, the same problem appears as:

236 

237```text theme={null}

238Invoke-Expression: Missing argument in parameter list.

239```

240 

241This means the install URL returned an HTML page instead of the install script. If the HTML page says "App unavailable in region," Claude Code is not available in your country. See [supported countries](https://www.anthropic.com/supported-countries).

242 

243Otherwise, this can happen due to network issues, regional routing, or a temporary service disruption.

244 

245**Solutions:**

246 

2471. **Use an alternative install method**:

248 

249 On macOS or Linux, install via Homebrew:

250 

251 ```bash theme={null}

252 brew install --cask claude-code

253 ```

254 

255 On Windows, install via WinGet:

256 

257 ```powershell theme={null}

258 winget install Anthropic.ClaudeCode

259 ```

260 

2612. **Retry after a few minutes**: the issue is often temporary. Wait and try the original command again.

262 

263### `command not found: claude` after installation

264 

265The install finished but `claude` doesn't work. The exact error varies by platform:

266 

267| Platform | Error message |

268| :---------- | :--------------------------------------------------------------------- |

269| macOS | `zsh: command not found: claude` |

270| Linux | `bash: claude: command not found` |

271| Windows CMD | `'claude' is not recognized as an internal or external command` |

272| PowerShell | `claude : The term 'claude' is not recognized as the name of a cmdlet` |

273 

274This means the install directory isn't in your shell's search path. See [Verify your PATH](#verify-your-path) for the fix on each platform.

275 

276### `curl: (56) Failure writing output to destination`

277 

278The `curl ... | bash` command downloads the script and passes it directly to Bash for execution using a pipe (`|`). This error means the connection broke before the script finished downloading. Common causes include network interruptions, the download being blocked mid-stream, or system resource limits.

279 

280**Solutions:**

281 

2821. **Check network stability**: Claude Code binaries are hosted at `downloads.claude.ai`. Test that you can reach it:

283 ```bash theme={null}

284 curl -fsSL https://downloads.claude.ai -o /dev/null

285 ```

286 If the command completes silently, your connection is fine and the issue is likely intermittent. Retry the install command. If you see an error, your network may be blocking the download.

287 

2882. **Try an alternative install method**:

289 

290 On macOS or Linux:

291 

292 ```bash theme={null}

293 brew install --cask claude-code

294 ```

295 

296 On Windows:

297 

298 ```powershell theme={null}

299 winget install Anthropic.ClaudeCode

300 ```

301 

302### TLS or SSL connection errors

303 

304Errors like `curl: (35) TLS connect error`, `schannel: next InitializeSecurityContext failed`, or PowerShell's `Could not establish trust relationship for the SSL/TLS secure channel` indicate TLS handshake failures.

305 

306**Solutions:**

307 

3081. **Update your system CA certificates**:

309 

310 On Ubuntu/Debian:

311 

312 ```bash theme={null}

313 sudo apt-get update && sudo apt-get install ca-certificates

314 ```

315 

316 On macOS via Homebrew:

317 

318 ```bash theme={null}

319 brew install ca-certificates

320 ```

321 

3222. **On Windows, enable TLS 1.2** in PowerShell before running the installer:

323 ```powershell theme={null}

324 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

325 irm https://claude.ai/install.ps1 | iex

326 ```

327 

3283. **Check for proxy or firewall interference**: corporate proxies that perform TLS inspection can cause these errors, including `unable to get local issuer certificate`. Set `NODE_EXTRA_CA_CERTS` to your corporate CA certificate bundle:

329 ```bash theme={null}

330 export NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem

331 ```

332 Ask your IT team for the certificate file if you don't have it. You can also try on a direct connection to confirm the proxy is the cause.

333 

3344. **On Windows, bypass certificate revocation checks** if you see `CRYPT_E_NO_REVOCATION_CHECK (0x80092012)` or `CRYPT_E_REVOCATION_OFFLINE (0x80092013)`. These mean curl reached the server but your network blocks the certificate revocation lookup, which is common behind corporate firewalls. Add `--ssl-revoke-best-effort` to the install command:

335 ```bat theme={null}

336 curl --ssl-revoke-best-effort -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd

337 ```

338 Alternatively, install with `winget install Anthropic.ClaudeCode`, which avoids curl entirely.

339 

340### `Failed to fetch version from downloads.claude.ai`

341 

342The installer couldn't reach the download server. This typically means `downloads.claude.ai` is blocked on your network.

343 

344**Solutions:**

345 

3461. **Test connectivity directly**:

347 ```bash theme={null}

348 curl -sI https://downloads.claude.ai

349 ```

350 

3512. **If behind a proxy**, set `HTTPS_PROXY` so the installer can route through it. See [proxy configuration](/en/network-config#proxy-configuration) for details.

352 ```bash theme={null}

353 export HTTPS_PROXY=http://proxy.example.com:8080

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

355 ```

356 

3573. **If on a restricted network**, try a different network or VPN, or use an alternative install method:

358 

359 On macOS or Linux:

360 

361 ```bash theme={null}

362 brew install --cask claude-code

363 ```

364 

365 On Windows:

366 

367 ```powershell theme={null}

368 winget install Anthropic.ClaudeCode

369 ```

370 

371### Windows: wrong install command

372 

373If you see `'irm' is not recognized`, `The token '&&' is not valid`, or `'bash' is not recognized as the name of a cmdlet`, you copied the install command for a different shell or operating system.

374 

375* **`irm` not recognized**: you're in CMD, not PowerShell. You have two options:

376 

377 Open PowerShell by searching for "PowerShell" in the Start menu, then run the original install command:

378 

379 ```powershell theme={null}

380 irm https://claude.ai/install.ps1 | iex

381 ```

382 

383 Or stay in CMD and use the CMD installer instead:

384 

385 ```batch theme={null}

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

387 ```

388 

389* **`&&` not valid**: you're in PowerShell but ran the CMD installer command. Use the PowerShell installer:

390 ```powershell theme={null}

391 irm https://claude.ai/install.ps1 | iex

392 ```

393 

394* **`bash` not recognized**: you ran the macOS/Linux installer on Windows. Use the PowerShell installer instead:

395 ```powershell theme={null}

396 irm https://claude.ai/install.ps1 | iex

397 ```

398 

399### Install killed on low-memory Linux servers

400 

401If you see `Killed` during installation on a VPS or cloud instance:

402 

403```text theme={null}

404Setting up Claude Code...

405Installing Claude Code native build latest...

406bash: line 142: 34803 Killed "$binary_path" install ${TARGET:+"$TARGET"}

407```

408 

409The Linux OOM killer terminated the process because the system ran out of memory. Claude Code requires at least 4 GB of available RAM.

410 

411**Solutions:**

412 

4131. **Add swap space** if your server has limited RAM. Swap uses disk space as overflow memory, letting the install complete even with low physical RAM.

414 

415 Create a 2 GB swap file and enable it:

416 

417 ```bash theme={null}

418 sudo fallocate -l 2G /swapfile

419 sudo chmod 600 /swapfile

420 sudo mkswap /swapfile

421 sudo swapon /swapfile

422 ```

423 

424 Then retry the installation:

425 

426 ```bash theme={null}

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

428 ```

429 

4302. **Close other processes** to free memory before installing.

431 

4323. **Use a larger instance** if possible. Claude Code requires at least 4 GB of RAM.

433 

434### Install hangs in Docker

435 

436When installing Claude Code in a Docker container, installing as root into `/` can cause hangs.

437 

438**Solutions:**

439 

4401. **Set a working directory** before running the installer. When run from `/`, the installer scans the entire filesystem, which causes excessive memory usage. Setting `WORKDIR` limits the scan to a small directory:

441 ```dockerfile theme={null}

442 WORKDIR /tmp

443 RUN curl -fsSL https://claude.ai/install.sh | bash

444 ```

445 

4462. **Increase Docker memory limits** if using Docker Desktop:

447 ```bash theme={null}

448 docker build --memory=4g .

449 ```

450 

451### Windows: Claude Desktop overrides `claude` CLI command

452 

453If you installed an older version of Claude Desktop, it may register a `Claude.exe` in the `WindowsApps` directory that takes PATH priority over Claude Code CLI. Running `claude` opens the Desktop app instead of the CLI.

454 

455Update Claude Desktop to the latest version to fix this issue.

456 

457### Windows: Claude Code on Windows requires git-bash

458 

459Claude Code on native Windows needs [Git for Windows](https://git-scm.com/downloads/win), which includes Git Bash.

460 

461**If Git is not installed**, download and install it from [git-scm.com/downloads/win](https://git-scm.com/downloads/win). During setup, select "Add to PATH." Restart your terminal after installing.

462 

463**If Git is already installed** but Claude Code still can't find it, set the path in your [settings.json file](/en/settings):

464 

465```json theme={null}

466{

467 "env": {

468 "CLAUDE_CODE_GIT_BASH_PATH": "C:\\Program Files\\Git\\bin\\bash.exe"

469 }

470}

471```

472 

473If your Git is installed somewhere else, find the path by running `where.exe git` in PowerShell and use the `bin\bash.exe` path from that directory.

474 

475### Windows: Claude Code does not support 32-bit Windows

476 

477Windows includes two PowerShell entries in the Start menu: `Windows PowerShell` and `Windows PowerShell (x86)`. The x86 entry runs as a 32-bit process and triggers this error even on a 64-bit machine. To check which case you're in, run this in the same window that produced the error:

478 

479```powershell theme={null}

480[Environment]::Is64BitOperatingSystem

481```

482 

483If this prints `True`, your operating system is fine. Close the window, open `Windows PowerShell` without the x86 suffix, and run the install command again.

484 

485If this prints `False`, you are on a 32-bit edition of Windows. Claude Code requires a 64-bit operating system. See the [system requirements](/en/setup#system-requirements).

486 

487### Linux: wrong binary variant installed (musl/glibc mismatch)

488 

489If you see errors about missing shared libraries like `libstdc++.so.6` or `libgcc_s.so.1` after installation, the installer may have downloaded the wrong binary variant for your system.

490 

491```text theme={null}

492Error loading shared library libstdc++.so.6: No such file or directory

493```

494 

495This can happen on glibc-based systems that have musl cross-compilation packages installed, causing the installer to misdetect the system as musl.

496 

497**Solutions:**

498 

4991. **Check which libc your system uses**:

500 ```bash theme={null}

501 ldd /bin/ls | head -1

502 ```

503 If it shows `linux-vdso.so` or references to `/lib/x86_64-linux-gnu/`, you're on glibc. If it shows `musl`, you're on musl.

504 

5052. **If you're on glibc but got the musl binary**, remove the installation and reinstall. You can also manually download the correct binary using the manifest at `https://downloads.claude.ai/claude-code-releases/{VERSION}/manifest.json`. File a [GitHub issue](https://github.com/anthropics/claude-code/issues) with the output of `ldd /bin/ls` and `ls /lib/libc.musl*`.

506 

5073. **If you're actually on musl** (Alpine Linux), install the required packages:

508 ```bash theme={null}

509 apk add libgcc libstdc++ ripgrep

510 ```

511 

512### `Illegal instruction` on Linux

513 

514If the installer prints `Illegal instruction` instead of the OOM `Killed` message, the downloaded binary doesn't match your CPU architecture. This commonly happens on ARM servers that receive an x86 binary, or on older CPUs that lack required instruction sets.

515 

516```text theme={null}

517bash: line 142: 2238232 Illegal instruction "$binary_path" install ${TARGET:+"$TARGET"}

518```

519 

520**Solutions:**

521 

5221. **Verify your architecture**:

523 ```bash theme={null}

524 uname -m

525 ```

526 `x86_64` means 64-bit Intel/AMD, `aarch64` means ARM64. If the binary doesn't match, [file a GitHub issue](https://github.com/anthropics/claude-code/issues) with the output.

527 

5282. **Try an alternative install method** while the architecture issue is resolved:

529 ```bash theme={null}

530 brew install --cask claude-code

531 ```

532 

533### `dyld: cannot load` on macOS

534 

535If you see `dyld: cannot load`, `dyld: Symbol not found`, or `Abort trap: 6` during installation, the binary is incompatible with your macOS version or hardware.

536 

537```text theme={null}

538dyld: cannot load 'claude-2.1.42-darwin-x64' (load command 0x80000034 is unknown)

539Abort trap: 6

540```

541 

542A `Symbol not found` error that references `libicucore` also indicates your macOS version is older than the binary supports:

543 

544```text theme={null}

545dyld: Symbol not found: _ubrk_clone

546 Referenced from: claude-darwin-x64 (which was built for Mac OS X 13.0)

547 Expected in: /usr/lib/libicucore.A.dylib

548```

549 

550**Solutions:**

551 

5521. **Check your macOS version**: Claude Code requires macOS 13.0 or later. Open the Apple menu and select About This Mac to check your version.

553 

5542. **Update macOS** if you're on an older version. The binary uses load commands that older macOS versions don't support.

555 

5563. **Try Homebrew** as an alternative install method:

557 ```bash theme={null}

558 brew install --cask claude-code

559 ```

560 

11### Windows installation issues: errors in WSL561### Windows installation issues: errors in WSL

12 562 

13You might encounter the following issues in WSL:563You might encounter the following issues in WSL:

14 564 

15**OS/platform detection issues**: If you receive an error during installation, WSL may be using Windows `npm`. Try:565**OS/platform detection issues**: if you receive an error during installation, WSL may be using Windows `npm`. Try:

16 566 

17* Run `npm config set os linux` before installation567* Run `npm config set os linux` before installation

18* Install with `npm install -g @anthropic-ai/claude-code --force --no-os-check` (Do NOT use `sudo`)568* Install with `npm install -g @anthropic-ai/claude-code --force --no-os-check`. Do not use `sudo`.

19 569 

20**Node not found errors**: If you see `exec: node: not found` when running `claude`, your WSL environment may be using a Windows installation of Node.js. You can confirm this with `which npm` and `which node`, which should point to Linux paths starting with `/usr/` rather than `/mnt/c/`. To fix this, try installing Node via your Linux distribution's package manager or via [`nvm`](https://github.com/nvm-sh/nvm).570**Node not found errors**: if you see `exec: node: not found` when running `claude`, your WSL environment may be using a Windows installation of Node.js. You can confirm this with `which npm` and `which node`, which should point to Linux paths starting with `/usr/` rather than `/mnt/c/`. To fix this, try installing Node via your Linux distribution's package manager or via [`nvm`](https://github.com/nvm-sh/nvm).

21 571 

22**nvm version conflicts**: If you have nvm installed in both WSL and Windows, you may experience version conflicts when switching Node versions in WSL. This happens because WSL imports the Windows PATH by default, causing Windows nvm/npm to take priority over the WSL installation.572**nvm version conflicts**: if you have nvm installed in both WSL and Windows, you may experience version conflicts when switching Node versions in WSL. This happens because WSL imports the Windows PATH by default, causing Windows nvm/npm to take priority over the WSL installation.

23 573 

24You can identify this issue by:574You can identify this issue by:

25 575 


54```604```

55 605 

56<Warning>606<Warning>

57 Avoid disabling Windows PATH importing (`appendWindowsPath = false`) as this breaks the ability to call Windows executables from WSL. Similarly, avoid uninstalling Node.js from Windows if you use it for Windows development.607 Avoid disabling Windows PATH importing via `appendWindowsPath = false` as this breaks the ability to call Windows executables from WSL. Similarly, avoid uninstalling Node.js from Windows if you use it for Windows development.

58</Warning>608</Warning>

59 609 

60### WSL2 sandbox setup610### WSL2 sandbox setup

61 611 

62[Sandboxing](/en/sandboxing) is supported on WSL2 but requires installing additional packages. If you see an error like "Sandbox requires socat and bubblewrap" when running `/sandbox`, install the dependencies:612[Sandboxing](/en/sandboxing) is supported on WSL2 but requires installing additional packages. If you see an error about missing `bubblewrap` or `socat` when running `/sandbox`, install the dependencies:

63 613 

64<Tabs>614<Tabs>

65 <Tab title="Ubuntu/Debian">615 <Tab title="Ubuntu/Debian">


77 627 

78WSL1 does not support sandboxing. If you see "Sandboxing requires WSL2", you need to upgrade to WSL2 or run Claude Code without sandboxing.628WSL1 does not support sandboxing. If you see "Sandboxing requires WSL2", you need to upgrade to WSL2 or run Claude Code without sandboxing.

79 629 

80### Linux and Mac installation issues: permission or command not found errors630Sandboxed commands cannot launch Windows binaries such as `cmd.exe`, `powershell.exe`, or executables under `/mnt/c/`. WSL hands these off to the Windows host over a Unix socket, which the sandbox blocks. If a command needs to invoke a Windows binary, add it to [`excludedCommands`](/en/settings#sandbox-settings) so it runs outside the sandbox.

81 

82When installing Claude Code with npm, `PATH` problems may prevent access to `claude`.

83You may also encounter permission errors if your npm global prefix is not user writable (for example, `/usr`, or `/usr/local`).

84 631 

85#### Recommended solution: Native Claude Code installation632### Permission errors during installation

86 633 

87Claude Code has a native installation that doesn't depend on npm or Node.js.634If the native installer fails with permission errors, the target directory may not be writable. See [Check directory permissions](#check-directory-permissions).

88 635 

89Use the following command to run the native installer.636If you previously installed with npm and are hitting npm-specific permission errors, switch to the native installer:

90 

91**macOS, Linux, WSL:**

92 637 

93```bash theme={null}638```bash theme={null}

94# Install stable version (default)

95curl -fsSL https://claude.ai/install.sh | bash639curl -fsSL https://claude.ai/install.sh | bash

640```

96 641 

97# Install latest version642### Native binary not found after npm install

98curl -fsSL https://claude.ai/install.sh | bash -s latest

99 643 

100# Install specific version number644The `@anthropic-ai/claude-code` npm package pulls in the native binary through a per-platform optional dependency such as `@anthropic-ai/claude-code-darwin-arm64`. If running `claude` after install prints `Could not find native binary package "@anthropic-ai/claude-code-<platform>"`, check the following causes:

101curl -fsSL https://claude.ai/install.sh | bash -s 1.0.58

102```

103 645 

104**Windows PowerShell:**646* **Optional dependencies are disabled.** Remove `--omit=optional` from your npm install command, `--no-optional` from pnpm, or `--ignore-optional` from yarn, and check that `.npmrc` does not set `optional=false`. Then reinstall. The native binary is delivered only as an optional dependency, so there is no JavaScript fallback if it is skipped.

647* **Unsupported platform.** Prebuilt binaries are published for `darwin-arm64`, `darwin-x64`, `linux-x64`, `linux-arm64`, `linux-x64-musl`, `linux-arm64-musl`, `win32-x64`, and `win32-arm64`. Claude Code does not ship a binary for other platforms; see the [system requirements](/en/setup#system-requirements).

648* **Corporate npm mirror is missing the platform packages.** Ensure your registry mirrors all eight `@anthropic-ai/claude-code-*` platform packages in addition to the meta package.

105 649 

106```powershell theme={null}650Installing with `--ignore-scripts` does not trigger this error. The postinstall step that links the binary into place is skipped, so Claude Code falls back to a wrapper that locates and spawns the platform binary on each launch. This works but starts more slowly; reinstall with scripts enabled for direct execution.

107# Install stable version (default)

108irm https://claude.ai/install.ps1 | iex

109 651 

110# Install latest version652## Permissions and authentication

111& ([scriptblock]::Create((irm https://claude.ai/install.ps1))) latest

112 653 

113# Install specific version number654These sections address login failures, token issues, and permission prompt behavior.

114& ([scriptblock]::Create((irm https://claude.ai/install.ps1))) 1.0.58

115 655 

116```656### Repeated permission prompts

117 657 

118This command installs the appropriate build of Claude Code for your operating system and architecture and adds a symlink to the installation at `~/.local/bin/claude` (or `%USERPROFILE%\.local\bin\claude.exe` on Windows).658If you find yourself repeatedly approving the same commands, you can allow specific tools

659to run without approval using the `/permissions` command. See [Permissions docs](/en/permissions#manage-permissions).

119 660 

120<Tip>661### Authentication issues

121 Make sure that you have the installation directory in your system PATH.

122</Tip>

123 662 

124### Windows: "Claude Code on Windows requires git-bash"663If you're experiencing authentication problems:

125 664 

126Claude Code on native Windows requires [Git for Windows](https://git-scm.com/downloads/win) which includes Git Bash. If Git is installed but not detected:6651. Run `/logout` to sign out completely

6662. Close Claude Code

6673. Restart with `claude` and complete the authentication process again

127 668 

1281. Set the path explicitly in PowerShell before running Claude:669If the browser doesn't open automatically during login, press `c` to copy the OAuth URL to your clipboard, then paste it into your browser manually.

129 ```powershell theme={null}

130 $env:CLAUDE_CODE_GIT_BASH_PATH="C:\Program Files\Git\bin\bash.exe"

131 ```

132 670 

1332. Or add it to your system environment variables permanently through System Properties Environment Variables.671### OAuth error: Invalid code

134 672 

135If Git is installed in a non-standard location, adjust the path accordingly.673If you see `OAuth error: Invalid code. Please make sure the full code was copied`, the login code expired or was truncated during copy-paste.

136 674 

137### Windows: "installMethod is native, but claude command not found"675**Solutions:**

138 676 

139If you see this error after installation, the `claude` command isn't in your PATH. Add it manually:677* Press Enter to retry and complete the login quickly after the browser opens

678* Type `c` to copy the full URL if the browser doesn't open automatically

679* If using a remote/SSH session, the browser may open on the wrong machine. Copy the URL displayed in the terminal and open it in your local browser instead.

140 680 

141<Steps>681### 403 Forbidden after login

142 <Step title="Open Environment Variables">

143 Press `Win + R`, type `sysdm.cpl`, and press Enter. Click **Advanced** → **Environment Variables**.

144 </Step>

145 682 

146 <Step title="Edit User PATH">683If you see `API Error: 403 {"error":{"type":"forbidden","message":"Request not allowed"}}` after logging in:

147 Under "User variables", select **Path** and click **Edit**. Click **New** and add:

148 684 

149 ```685* **Claude Pro/Max users**: verify your subscription is active at [claude.ai/settings](https://claude.ai/settings)

150 %USERPROFILE%\.local\bin686* **Console users**: confirm your account has the "Claude Code" or "Developer" role assigned by your admin

151 ```687* **Behind a proxy**: corporate proxies can interfere with API requests. See [network configuration](/en/network-config) for proxy setup.

152 </Step>

153 688 

154 <Step title="Restart your terminal">689### Model not found or not accessible

155 Close and reopen PowerShell or CMD for changes to take effect.

156 </Step>

157</Steps>

158 690 

159Verify installation:691If you see `There's an issue with the selected model (...). It may not exist or you may not have access to it`, the API rejected the configured model name.

160 692 

161```bash theme={null}693Common causes:

162claude doctor # Check installation health

163```

164 694 

165## Permissions and authentication695* A typo in the model name passed to `--model`

696* A stale or deprecated model ID saved in your settings

697* An API key without access to that model on your current usage tier

166 698 

167### Repeated permission prompts699Check where the model is set, in [priority order](/en/model-config#setting-your-model):

168 700 

169If you find yourself repeatedly approving the same commands, you can allow specific tools701* The `--model` flag

170to run without approval using the `/permissions` command. See [Permissions docs](/en/iam#configuring-permissions).702* The `ANTHROPIC_MODEL` environment variable

703* The `model` field in `.claude/settings.local.json`

704* The `model` field in your project's `.claude/settings.json`

705* The `model` field in `~/.claude/settings.json`

171 706 

172### Authentication issues707To clear a stale value, remove the `model` field from your settings or unset `ANTHROPIC_MODEL`, and Claude Code will fall back to the default model for your account.

173 708 

174If you're experiencing authentication problems:709To browse models available to your account, start `claude` interactively and run `/model` to open the picker. For Vertex AI deployments, see [the Vertex AI troubleshooting section](/en/google-vertex-ai#troubleshooting).

175 710 

1761. Run `/logout` to sign out completely711### This organization has been disabled with an active subscription

1772. Close Claude Code

1783. Restart with `claude` and complete the authentication process again

179 712 

180If the browser doesn't open automatically during login, press `c` to copy the OAuth URL to your clipboard, then paste it into your browser manually.713If you see `API Error: 400 ... "This organization has been disabled"` despite having an active Claude subscription, an `ANTHROPIC_API_KEY` environment variable is overriding your subscription. This commonly happens when an old API key from a previous employer or project is still set in your shell profile.

181 714 

182If problems persist, try:715When `ANTHROPIC_API_KEY` is present and you have approved it, Claude Code uses that key instead of your subscription's OAuth credentials. In non-interactive mode (`-p`), the key is always used when present. See [authentication precedence](/en/authentication#authentication-precedence) for the full resolution order.

716 

717To use your subscription instead, unset the environment variable and remove it from your shell profile:

183 718 

184```bash theme={null}719```bash theme={null}

185rm -rf ~/.config/claude-code/auth.json720unset ANTHROPIC_API_KEY

186claude721claude

187```722```

188 723 

189This removes your stored authentication information and forces a clean login.724Check `~/.zshrc`, `~/.bashrc`, or `~/.profile` for `export ANTHROPIC_API_KEY=...` lines and remove them to make the change permanent. Run `/status` inside Claude Code to confirm which authentication method is active.

725 

726### OAuth login fails in WSL2

727 

728Browser-based login in WSL2 may fail if WSL can't open your Windows browser. Set the `BROWSER` environment variable:

729 

730```bash theme={null}

731export BROWSER="/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"

732claude

733```

734 

735Or copy the URL manually: when the login prompt appears, press `c` to copy the OAuth URL, then paste it into your Windows browser.

736 

737### Not logged in or token expired

738 

739If Claude Code prompts you to log in again after a session, your OAuth token may have expired.

740 

741Run `/login` to re-authenticate. If this happens frequently, check that your system clock is accurate, as token validation depends on correct timestamps.

742 

743On macOS, login can also fail when the Keychain is locked or its password is out of sync with your account password, which prevents Claude Code from saving credentials. Run `claude doctor` to check Keychain access. To unlock the Keychain manually, run `security unlock-keychain ~/Library/Keychains/login.keychain-db`. If unlocking doesn't help, open Keychain Access, select the `login` keychain, and choose Edit > Change Password for Keychain "login" to resync it with your account password.

190 744 

191## Configuration file locations745## Configuration file locations

192 746 

193Claude Code stores configuration in several locations:747Claude Code stores configuration in several locations:

194 748 

195| File | Purpose |749| File | Purpose |

196| :---------------------------- | :------------------------------------------------------- |750| :---------------------------- | :----------------------------------------------------------------------------------------------------- |

197| `~/.claude/settings.json` | User settings (permissions, hooks, model overrides) |751| `~/.claude/settings.json` | User settings (permissions, hooks, model overrides) |

198| `.claude/settings.json` | Project settings (checked into source control) |752| `.claude/settings.json` | Project settings (checked into source control) |

199| `.claude/settings.local.json` | Local project settings (not committed) |753| `.claude/settings.local.json` | Local project settings (not committed) |

200| `~/.claude.json` | Global state (theme, OAuth, MCP servers) |754| `~/.claude.json` | Global state (theme, OAuth, MCP servers) |

201| `.mcp.json` | Project MCP servers (checked into source control) |755| `.mcp.json` | Project MCP servers (checked into source control) |

202| `managed-settings.json` | [Managed settings](/en/settings#settings-files) |

203| `managed-mcp.json` | [Managed MCP servers](/en/mcp#managed-mcp-configuration) |756| `managed-mcp.json` | [Managed MCP servers](/en/mcp#managed-mcp-configuration) |

757| Managed settings | [Managed settings](/en/settings#settings-files) (server-managed, MDM/OS-level policies, or file-based) |

204 758 

205On Windows, `~` refers to your user home directory, such as `C:\Users\YourName`.759On Windows, `~` refers to your user home directory, such as `C:\Users\YourName`.

206 760 

207**Managed file locations:**

208 

209* macOS: `/Library/Application Support/ClaudeCode/`

210* Linux/WSL: `/etc/claude-code/`

211* Windows: `C:\Program Files\ClaudeCode\`

212 

213For details on configuring these files, see [Settings](/en/settings) and [MCP](/en/mcp).761For details on configuring these files, see [Settings](/en/settings) and [MCP](/en/mcp).

214 762 

215### Resetting configuration763### Resetting configuration


232 780 

233## Performance and stability781## Performance and stability

234 782 

783These sections cover issues related to resource usage, responsiveness, and search behavior.

784 

235### High CPU or memory usage785### High CPU or memory usage

236 786 

237Claude Code is designed to work with most development environments, but may consume significant resources when processing large codebases. If you're experiencing performance issues:787Claude Code is designed to work with most development environments, but may consume significant resources when processing large codebases. If you're experiencing performance issues:


2402. Close and restart Claude Code between major tasks7902. Close and restart Claude Code between major tasks

2413. Consider adding large build directories to your `.gitignore` file7913. Consider adding large build directories to your `.gitignore` file

242 792 

793If memory usage stays high after these steps, run `/heapdump` to write a JavaScript heap snapshot and a memory breakdown to `~/Desktop`. The breakdown shows resident set size, JS heap, array buffers, and unaccounted native memory, which helps identify whether the growth is in JavaScript objects or in native code. Open the `.heapsnapshot` file in Chrome DevTools under Memory → Load to inspect retainers. Attach both files when reporting a memory issue on [GitHub](https://github.com/anthropics/claude-code/issues).

794 

795### Auto-compaction stops with a thrashing error

796 

797If you see `Autocompact is thrashing: the context refilled to the limit...`, automatic compaction succeeded but a file or tool output immediately refilled the context window several times in a row. Claude Code stops retrying to avoid wasting API calls on a loop that isn't making progress.

798 

799To recover:

800 

8011. Ask Claude to read the oversized file in smaller chunks, such as a specific line range or function, instead of the whole file

8022. Run `/compact` with a focus that drops the large output, for example `/compact keep only the plan and the diff`

8033. Move the large-file work to a [subagent](/en/sub-agents) so it runs in a separate context window

8044. Run `/clear` if the earlier conversation is no longer needed

805 

243### Command hangs or freezes806### Command hangs or freezes

244 807 

245If Claude Code seems unresponsive:808If Claude Code seems unresponsive:


268pacman -S ripgrep831pacman -S ripgrep

269```832```

270 833 

271Then set `USE_BUILTIN_RIPGREP=0` in your [environment](/en/settings#environment-variables).834Then set `USE_BUILTIN_RIPGREP=0` in your [environment](/en/env-vars).

272 835 

273### Slow or incomplete search results on WSL836### Slow or incomplete search results on WSL

274 837 

275Disk read performance penalties when [working across file systems on WSL](https://learn.microsoft.com/en-us/windows/wsl/filesystems) may result in fewer-than-expected matches (but not a complete lack of search functionality) when using Claude Code on WSL.838Disk read performance penalties when [working across file systems on WSL](https://learn.microsoft.com/en-us/windows/wsl/filesystems) may result in fewer-than-expected matches when using Claude Code on WSL. Search still functions, but returns fewer results than on a native filesystem.

276 839 

277<Note>840<Note>

278 `/doctor` will show Search as OK in this case.841 `/doctor` will show Search as OK in this case.


280 843 

281**Solutions:**844**Solutions:**

282 845 

2831. **Submit more specific searches**: Reduce the number of files searched by specifying directories or file types: "Search for JWT validation logic in the auth-service package" or "Find use of md5 hash in JS files".8461. **Submit more specific searches**: reduce the number of files searched by specifying directories or file types: "Search for JWT validation logic in the auth-service package" or "Find use of md5 hash in JS files".

284 847 

2852. **Move project to Linux filesystem**: If possible, ensure your project is located on the Linux filesystem (`/home/`) rather than the Windows filesystem (`/mnt/c/`).8482. **Move project to Linux filesystem**: if possible, ensure your project is located on the Linux filesystem (`/home/`) rather than the Windows filesystem (`/mnt/c/`).

286 849 

2873. **Use native Windows instead**: Consider running Claude Code natively on Windows instead of through WSL, for better file system performance.8503. **Use native Windows instead**: consider running Claude Code natively on Windows instead of through WSL, for better file system performance.

288 851 

289## IDE integration issues852## IDE integration issues

290 853 

854If Claude Code does not connect to your IDE or behaves unexpectedly within an IDE terminal, try the solutions below.

855 

291### JetBrains IDE not detected on WSL2856### JetBrains IDE not detected on WSL2

292 857 

293If you're using Claude Code on WSL2 with JetBrains IDEs and getting "No available IDEs detected" errors, this is likely due to WSL2's networking configuration or Windows Firewall blocking the connection.858If you're using Claude Code on WSL2 with JetBrains IDEs and getting "No available IDEs detected" errors, this is likely due to WSL2's networking configuration or Windows Firewall blocking the connection.


3011. Find your WSL2 IP address:8661. Find your WSL2 IP address:

302 ```bash theme={null}867 ```bash theme={null}

303 wsl hostname -I868 wsl hostname -I

304 # Example output: 172.21.123.456869 # Example output: 172.21.123.45

305 ```870 ```

306 871 

3072. Open PowerShell as Administrator and create a firewall rule:8722. Open PowerShell as Administrator and create a firewall rule:

308 ```powershell theme={null}873 ```powershell theme={null}

309 New-NetFirewallRule -DisplayName "Allow WSL2 Internal Traffic" -Direction Inbound -Protocol TCP -Action Allow -RemoteAddress 172.21.0.0/16 -LocalAddress 172.21.0.0/16874 New-NetFirewallRule -DisplayName "Allow WSL2 Internal Traffic" -Direction Inbound -Protocol TCP -Action Allow -RemoteAddress 172.21.0.0/16 -LocalAddress 172.21.0.0/16

310 ```875 ```

311 (Adjust the IP range based on your WSL2 subnet from step 1)876 Adjust the IP range based on your WSL2 subnet from step 1.

312 877 

3133. Restart both your IDE and Claude Code8783. Restart both your IDE and Claude Code

314 879 


327 These networking issues only affect WSL2. WSL1 uses the host's network directly and doesn't require these configurations.892 These networking issues only affect WSL2. WSL1 uses the host's network directly and doesn't require these configurations.

328</Note>893</Note>

329 894 

330For additional JetBrains configuration tips, see our [JetBrains IDE guide](/en/jetbrains#plugin-settings).895For additional JetBrains configuration tips, see the [JetBrains IDE guide](/en/jetbrains#plugin-settings).

331 896 

332### Reporting Windows IDE integration issues (both native and WSL)897### Report Windows IDE integration issues

333 898 

334If you're experiencing IDE integration problems on Windows, [create an issue](https://github.com/anthropics/claude-code/issues) with the following information:899If you're experiencing IDE integration problems on Windows, [create an issue](https://github.com/anthropics/claude-code/issues) with the following information:

335 900 

336* Environment type: native Windows (Git Bash) or WSL1/WSL2901* Environment type: native Windows (Git Bash) or WSL1/WSL2

337* WSL networking mode (if applicable): NAT or mirrored902* WSL networking mode, if applicable: NAT or mirrored

338* IDE name and version903* IDE name and version

339* Claude Code extension/plugin version904* Claude Code extension/plugin version

340* Shell type: Bash, Zsh, PowerShell, etc.905* Shell type: Bash, Zsh, PowerShell, etc.

341 906 

342### Escape key not working in JetBrains (IntelliJ, PyCharm, etc.) terminals907### Escape key not working in JetBrains IDE terminals

343 908 

344If you're using Claude Code in JetBrains terminals and the `Esc` key doesn't interrupt the agent as expected, this is likely due to a keybinding clash with JetBrains' default shortcuts.909If you're using Claude Code in JetBrains terminals and the `Esc` key doesn't interrupt the agent as expected, this is likely due to a keybinding clash with JetBrains' default shortcuts.

345 910 


381 946 

382**Solutions:**947**Solutions:**

383 948 

3841. **Ask Claude to add language tags**: Request "Add appropriate language tags to all code blocks in this markdown file."9491. **Ask Claude to add language tags**: request "Add appropriate language tags to all code blocks in this markdown file."

385 950 

3862. **Use post-processing hooks**: Set up automatic formatting hooks to detect and add missing language tags. See [Auto-format code after edits](/en/hooks-guide#auto-format-code-after-edits) for an example of a PostToolUse formatting hook.9512. **Use post-processing hooks**: set up automatic formatting hooks to detect and add missing language tags. See [Auto-format code after edits](/en/hooks-guide#auto-format-code-after-edits) for an example of a PostToolUse formatting hook.

387 952 

3883. **Manual verification**: After generating markdown files, review them for proper code block formatting and request corrections if needed.9533. **Manual verification**: after generating markdown files, review them for proper code block formatting and request corrections if needed.

389 954 

390### Inconsistent spacing and formatting955### Inconsistent spacing and formatting

391 956 


393 958 

394**Solutions:**959**Solutions:**

395 960 

3961. **Request formatting corrections**: Ask Claude to "Fix spacing and formatting issues in this markdown file."9611. **Request formatting corrections**: ask Claude to "Fix spacing and formatting issues in this markdown file."

397 962 

3982. **Use formatting tools**: Set up hooks to run markdown formatters like `prettier` or custom formatting scripts on generated markdown files.9632. **Use formatting tools**: set up hooks to run markdown formatters like `prettier` or custom formatting scripts on generated markdown files.

399 964 

4003. **Specify formatting preferences**: Include formatting requirements in your prompts or project [memory](/en/memory) files.9653. **Specify formatting preferences**: include formatting requirements in your prompts or project [memory](/en/memory) files.

401 966 

402### Best practices for markdown generation967### Reduce markdown formatting issues

403 968 

404To minimize formatting issues:969To minimize formatting issues:

405 970 

406* **Be explicit in requests**: Ask for "properly formatted markdown with language-tagged code blocks"971* **Be explicit in requests**: ask for "properly formatted markdown with language-tagged code blocks"

407* **Use project conventions**: Document your preferred markdown style in [`CLAUDE.md`](/en/memory)972* **Use project conventions**: document your preferred markdown style in [`CLAUDE.md`](/en/memory)

408* **Set up validation hooks**: Use post-processing hooks to automatically verify and fix common formatting issues973* **Set up validation hooks**: use post-processing hooks to automatically verify and fix common formatting issues

409 974 

410## Getting more help975## Get more help

411 976 

412If you're experiencing issues not covered here:977If you're experiencing issues not covered here:

413 978 

4141. Use the `/bug` command within Claude Code to report problems directly to Anthropic9791. See the [Error reference](/en/errors) for `API Error: 5xx`, `529 Overloaded`, `429`, and request validation errors that appear during a session

4152. Check the [GitHub repository](https://github.com/anthropics/claude-code) for known issues9802. Use the `/feedback` command within Claude Code to report problems directly to Anthropic

4163. Run `/doctor` to diagnose issues. It checks:9813. Check the [GitHub repository](https://github.com/anthropics/claude-code) for known issues

9824. Run `/doctor` to diagnose issues. It checks:

417 * Installation type, version, and search functionality983 * Installation type, version, and search functionality

418 * Auto-update status and available versions984 * Auto-update status and available versions

419 * Invalid settings files (malformed JSON, incorrect types)985 * Invalid settings files (malformed JSON, incorrect types)

420 * MCP server configuration errors986 * MCP server configuration errors, including the same server name defined in multiple scopes with different endpoints

421 * Keybinding configuration problems987 * Keybinding configuration problems

422 * Context usage warnings (large CLAUDE.md files, high MCP token usage, unreachable permission rules)988 * Context usage warnings (large CLAUDE.md files, high MCP token usage, unreachable permission rules)

423 * Plugin and agent loading errors989 * Plugin and agent loading errors

4244. Ask Claude directly about its capabilities and features - Claude has built-in access to its documentation9905. Ask Claude directly about its capabilities and features - Claude has built-in access to its documentation

ultraplan.md +84 −0 added

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# Plan in the cloud with ultraplan

6 

7> Start a plan from your CLI, draft it on Claude Code on the web, then execute it remotely or back in your terminal

8 

9<Note>

10 Ultraplan is in research preview and requires Claude Code v2.1.91 or later. Behavior and capabilities may change based on feedback.

11</Note>

12 

13Ultraplan hands a planning task from your local CLI to a [Claude Code on the web](/en/claude-code-on-the-web) session running in [plan mode](/en/permission-modes#analyze-before-you-edit-with-plan-mode). Claude drafts the plan in the cloud while you keep working in your terminal. When the plan is ready, you open it in your browser to comment on specific sections, ask for revisions, and choose where to execute it.

14 

15This is useful when you want a richer review surface than the terminal offers:

16 

17* **Targeted feedback**: comment on individual sections of the plan instead of replying to the whole thing

18* **Hands-off drafting**: the plan is generated remotely, so your terminal stays free for other work

19* **Flexible execution**: approve the plan to run on the web and open a pull request, or send it back to your terminal

20 

21Ultraplan requires a [Claude Code on the web](/en/claude-code-on-the-web) account and a GitHub repository. Because it runs on Anthropic's cloud infrastructure, it is not available when using Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry. The cloud session runs in your account's default [cloud environment](/en/claude-code-on-the-web#the-cloud-environment). If you don't have a cloud environment yet, ultraplan creates one automatically when it first launches.

22 

23## Launch ultraplan from the CLI

24 

25From your local CLI session, you can launch ultraplan in three ways:

26 

27* **Command**: run `/ultraplan` followed by your prompt

28* **Keyword**: include the word `ultraplan` anywhere in a normal prompt

29* **From a local plan**: when Claude finishes a local plan and shows the approval dialog, choose **No, refine with Ultraplan on Claude Code on the web** to send the draft to the cloud for further iteration

30 

31For example, to plan a service migration with the command:

32 

33```

34/ultraplan migrate the auth service from sessions to JWTs

35```

36 

37The command and keyword paths open a confirmation dialog before launching. The local plan path skips this dialog because that selection already serves as confirmation. If [Remote Control](/en/remote-control) is active, it disconnects when ultraplan starts because both features occupy the claude.ai/code interface and only one can be connected at a time.

38 

39After the cloud session launches, your CLI's prompt input shows a status indicator while the remote session works:

40 

41| Status | Meaning |

42| :----------------------------- | :----------------------------------------------------------------- |

43| `◇ ultraplan` | Claude is researching your codebase and drafting the plan |

44| `◇ ultraplan needs your input` | Claude has a clarifying question; open the session link to respond |

45| `◆ ultraplan ready` | The plan is ready to review in your browser |

46 

47Run `/tasks` and select the ultraplan entry to open a detail view with the session link, agent activity, and a **Stop ultraplan** action. Stopping archives the cloud session and clears the indicator; nothing is saved to your terminal.

48 

49## Review and revise the plan in your browser

50 

51When the status changes to `◆ ultraplan ready`, open the session link to view the plan on claude.ai. The plan appears in a dedicated review view:

52 

53* **Inline comments**: highlight any passage and leave a comment for Claude to address

54* **Emoji reactions**: react to a section to signal approval or concern without writing a full comment

55* **Outline sidebar**: jump between sections of the plan

56 

57When you ask Claude to address your comments, it revises the plan and presents an updated draft. You can iterate as many times as needed before choosing where to execute.

58 

59## Choose where to execute

60 

61When the plan looks right, you choose from the browser whether Claude implements it in the same cloud session or sends it back to your waiting terminal.

62 

63### Execute on the web

64 

65Select **Approve Claude's plan and start coding** in your browser to have Claude implement it in the same Claude Code on the web session. Your terminal shows a confirmation, the status indicator clears, and the work continues in the cloud. When the implementation finishes, [review the diff](/en/claude-code-on-the-web#review-changes) and create a pull request from the web interface.

66 

67### Send the plan back to your terminal

68 

69Select **Approve plan and teleport back to terminal** in your browser to implement the plan locally with full access to your environment. This option appears when the session was launched from your CLI and the terminal is still polling. The web session is archived so it doesn't continue working in parallel.

70 

71Your terminal shows the plan in a dialog titled **Ultraplan approved** with three options:

72 

73* **Implement here**: inject the plan into your current conversation and continue from where you left off

74* **Start new session**: clear the current conversation and begin fresh with only the plan as context

75* **Cancel**: save the plan to a file without executing it; Claude prints the file path so you can return to it later

76 

77If you start a new session, Claude prints a `claude --resume` command at the top so you can return to your previous conversation later.

78 

79## Related resources

80 

81* [Claude Code on the web](/en/claude-code-on-the-web): the cloud infrastructure ultraplan runs on

82* [Plan mode](/en/permission-modes#analyze-before-you-edit-with-plan-mode): how planning works in a local session

83* [Find bugs with ultrareview](/en/ultrareview): the code review counterpart to ultraplan for catching issues before merge

84* [Remote Control](/en/remote-control): use the claude.ai/code interface with a session running on your own machine

ultrareview.md +85 −0 added

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# Find bugs with ultrareview

6 

7> Run a deep, multi-agent code review in the cloud with /ultrareview to find and verify bugs before you merge.

8 

9<Note>

10 Ultrareview is a research preview feature available in Claude Code v2.1.86 and later. The feature, pricing, and availability may change based on feedback.

11</Note>

12 

13Ultrareview is a deep code review that runs on Claude Code on the web infrastructure. When you run `/ultrareview`, Claude Code launches a fleet of reviewer agents in a remote sandbox to find bugs in your branch or pull request.

14 

15Compared to a local `/review`, ultrareview offers:

16 

17* **Higher signal**: every reported finding is independently reproduced and verified, so the results focus on real bugs rather than style suggestions

18* **Broader coverage**: many reviewer agents explore the change in parallel, which surfaces issues that a single-pass review can miss

19* **No local resource use**: the review runs entirely in a remote sandbox, so your terminal stays free for other work while it runs

20 

21Ultrareview requires authentication with a Claude.ai account because it runs on Claude Code on the web infrastructure. If you are signed in with an API key only, run `/login` and authenticate with Claude.ai first. Ultrareview is not available when using Claude Code with Amazon Bedrock, Google Cloud Vertex AI, or Microsoft Foundry, and it is not available to organizations that have enabled Zero Data Retention.

22 

23## Run ultrareview from the CLI

24 

25Start a review from any git repository in the Claude Code CLI.

26 

27```text theme={null}

28/ultrareview

29```

30 

31Without arguments, ultrareview reviews the diff between your current branch and the default branch, including any uncommitted and staged changes in your working tree. Claude Code bundles the repository state and uploads it to a remote sandbox for the review.

32 

33To review a GitHub pull request instead, pass the PR number.

34 

35```text theme={null}

36/ultrareview 1234

37```

38 

39In PR mode, the remote sandbox clones the pull request directly from GitHub rather than bundling your local working tree. PR mode requires a `github.com` remote on the repository.

40 

41<Tip>

42 If your repository is too large to bundle, Claude Code prompts you to use PR mode instead. Push your branch and open a draft PR, then run `/ultrareview <PR-number>`.

43</Tip>

44 

45Before launching, Claude Code shows a confirmation dialog with the review scope (including the file and line count when reviewing a branch), your remaining free runs, and the estimated cost. After you confirm, the review continues in the background and you can keep using your session. The command runs only when you invoke it with `/ultrareview`; Claude does not start an ultrareview on its own.

46 

47## Pricing and free runs

48 

49Ultrareview is a premium feature that bills against extra usage rather than your plan's included usage.

50 

51| Plan | Included free runs | After free runs |

52| ------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------- |

53| Pro | 3 free runs through May 5, 2026 | billed as [extra usage](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |

54| Max | 3 free runs through May 5, 2026 | billed as [extra usage](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |

55| Team and Enterprise | none | billed as [extra usage](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |

56 

57Pro and Max subscribers receive three free ultrareview runs to try the feature. These three runs are a one-time allotment per account, do not refresh, and expire on May 5, 2026. After you use all three, or after the free run period ends, each review is billed to extra usage and typically costs \$5 to \$20 depending on the size of the change.

58 

59Because ultrareview always bills as extra usage outside the free runs, your account or organization must have extra usage enabled before you can launch a paid review. If extra usage is not enabled, Claude Code blocks the launch and links you to the billing settings where you can turn it on. You can also run `/extra-usage` to check or change your current setting.

60 

61## Track a running review

62 

63A review typically takes 5 to 10 minutes. The review runs as a background task, so you can keep working in your session, start other commands, or close the terminal entirely.

64 

65Use `/tasks` to see running and completed reviews, open the detail view for a review, or stop a review that is in progress. Stopping a review archives the cloud session, and partial findings are not returned. When the review finishes, the verified findings appear as a notification in your session. Each finding includes the file location and an explanation of the issue so you can ask Claude to fix it directly.

66 

67## How ultrareview compares to /review

68 

69Both commands review code, but they target different stages of your workflow.

70 

71| | `/review` | `/ultrareview` |

72| -------- | ------------------------------ | ------------------------------------------------------------- |

73| Runs | locally in your session | remotely in a cloud sandbox |

74| Depth | single-pass review | multi-agent fleet with independent verification |

75| Duration | seconds to a few minutes | roughly 5 to 10 minutes |

76| Cost | counts toward normal usage | free runs, then roughly \$5 to \$20 per review as extra usage |

77| Best for | quick feedback while iterating | pre-merge confidence on substantial changes |

78 

79Use `/review` for fast feedback as you work. Use `/ultrareview` before merging a substantial change when you want a deeper pass that catches issues a single review might miss.

80 

81## Related resources

82 

83* [Claude Code on the web](/en/claude-code-on-the-web): learn how remote sessions and cloud sandboxes work

84* [Plan complex changes with ultraplan](/en/ultraplan): the planning counterpart to ultrareview for upfront design work

85* [Manage costs effectively](/en/costs): track usage and set spending limits

voice-dictation.md +189 −0 added

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# Voice dictation

6 

7> Speak your prompts in the Claude Code CLI with hold-to-record or tap-to-record voice dictation.

8 

9Speak your prompts instead of typing them in the Claude Code CLI. Your speech is transcribed live into the prompt input, so you can mix voice and typing in the same message. Enable dictation with `/voice`, then either hold a key while you speak or tap once to start and again to send.

10 

11<Note>

12 Voice dictation requires Claude Code v2.1.69 or later. Tap mode requires v2.1.116 or later. Check your version with `claude --version`.

13</Note>

14 

15## Requirements

16 

17Voice dictation streams your recorded audio to Anthropic's servers for transcription. Audio is not processed locally. The speech-to-text service is only available when you authenticate with a Claude.ai account, and is not available when Claude Code is configured to use an Anthropic API key directly, Amazon Bedrock, Google Vertex AI, or Microsoft Foundry. Transcription does not consume Claude messages or tokens and does not count toward the limits shown in `/usage`. See [data usage](/en/data-usage) for how Anthropic handles your data.

18 

19Voice dictation also needs local microphone access, so it does not work in remote environments such as [Claude Code on the web](/en/claude-code-on-the-web) or SSH sessions. In WSL, voice dictation requires WSLg for audio access, which is included with WSL2 on Windows 11. On Windows 10 or WSL1, run Claude Code in native Windows instead.

20 

21Audio recording uses a built-in native module on macOS, Linux, and Windows. On Linux, if the native module cannot load, Claude Code falls back to `arecord` from ALSA utils or `rec` from SoX. If neither is available, `/voice` prints an install command for your package manager.

22 

23The Claude Code [VS Code extension](/en/vs-code) also supports voice dictation with the same Claude.ai account requirement. It is not available in VS Code Remote sessions, including SSH, Dev Containers, and Codespaces, because the microphone is on your local machine and the extension runs on the remote host.

24 

25## Enable voice dictation

26 

27Run `/voice` to enable dictation. The first time you enable it, Claude Code runs a microphone check. On macOS, this triggers the system microphone permission prompt for your terminal if it has never been granted.

28 

29```

30/voice

31Voice mode enabled (hold). Hold Space to record. Dictation language: en (/config to change).

32```

33 

34`/voice` accepts an optional mode argument:

35 

36| Command | Effect |

37| :------------ | :-------------------------------------------- |

38| `/voice` | Toggle on or off, keep the current mode |

39| `/voice hold` | Enable in [hold mode](#hold-to-record) |

40| `/voice tap` | Enable in [tap mode](#tap-to-record-and-send) |

41| `/voice off` | Disable |

42 

43Voice dictation persists across sessions. Set it directly in your [user settings file](/en/settings) instead of running `/voice`:

44 

45```json theme={null}

46{

47 "voice": {

48 "enabled": true,

49 "mode": "tap"

50 }

51}

52```

53 

54While voice dictation is enabled, the input footer shows a `hold Space to speak` hint when the prompt is empty. The hint text is the same in both modes, and it does not appear if you have a [custom status line](/en/statusline) configured.

55 

56Transcription is tuned for coding vocabulary in both modes. Common development terms like `regex`, `OAuth`, `JSON`, and `localhost` are recognized correctly, and your current project name and git branch name are added as recognition hints automatically.

57 

58## Hold to record

59 

60Hold mode is push-to-talk: recording runs while you hold the key and stops when you release it. This is the default mode.

61 

62Hold `Space` to start recording. Claude Code detects a held key by watching for rapid key-repeat events from your terminal, so there is a brief warmup before recording begins. The footer shows `keep holding…` during warmup, then switches to a live waveform once recording is active.

63 

64The first couple of key-repeat characters type into the input during warmup and are removed automatically when recording activates. A single `Space` tap still types a space, since hold detection only triggers on rapid repeat.

65 

66<Tip>

67 To skip the warmup, switch to [tap mode](#tap-to-record-and-send) with `/voice tap`, or [rebind to a modifier combination](#rebind-the-dictation-key) like `meta+k`. Modifier combos start recording on the first keypress.

68</Tip>

69 

70Your speech appears in the prompt as you speak, dimmed until the transcript is finalized. Release `Space` to stop recording and finalize the text. The transcript is inserted at your cursor position and the cursor stays at the end of the inserted text, so you can mix typing and dictation in any order. Hold `Space` again to append another recording, or move the cursor first to insert speech elsewhere in the prompt:

71 

72```

73> refactor the auth middleware to ▮

74 # hold Space, speak "use the new token validation helper"

75> refactor the auth middleware to use the new token validation helper▮

76```

77 

78By default, releasing the key inserts the transcript and waits for you to press `Enter`. Set `"autoSubmit": true` in the `voice` settings object to send the prompt automatically when you release the key, as long as the transcript is at least three words long.

79 

80## Tap to record and send

81 

82Tap mode toggles recording with a single keypress: tap once to start, speak, then tap again to send the prompt. There is no warmup, and you do not need to keep the key held.

83 

84Enable tap mode with `/voice tap`. With the prompt input empty, tap `Space` to start recording. The footer shows a live waveform while recording. Tap `Space` again to stop. Claude Code inserts the transcript and submits the prompt automatically when the transcript is at least three words long. Shorter transcripts are inserted but not submitted, so an accidental tap does not send a stray word.

85 

86The first tap only starts recording when the prompt input is empty, so you can still type spaces normally while composing a message. The second tap stops recording regardless of input contents. Recording also stops automatically after 15 seconds of silence or two minutes total.

87 

88## Change the dictation language

89 

90Voice dictation uses the same [`language` setting](/en/settings) that controls Claude's response language. If that setting is empty, dictation defaults to English.

91 

92<Accordion title="Supported dictation languages">

93 | Language | Code |

94 | :--------- | :--- |

95 | Czech | `cs` |

96 | Danish | `da` |

97 | Dutch | `nl` |

98 | English | `en` |

99 | French | `fr` |

100 | German | `de` |

101 | Greek | `el` |

102 | Hindi | `hi` |

103 | Indonesian | `id` |

104 | Italian | `it` |

105 | Japanese | `ja` |

106 | Korean | `ko` |

107 | Norwegian | `no` |

108 | Polish | `pl` |

109 | Portuguese | `pt` |

110 | Russian | `ru` |

111 | Spanish | `es` |

112 | Swedish | `sv` |

113 | Turkish | `tr` |

114 | Ukrainian | `uk` |

115</Accordion>

116 

117Set the language in `/config` or directly in settings. You can use either the [BCP 47 language code](https://en.wikipedia.org/wiki/IETF_language_tag) or the language name:

118 

119```json theme={null}

120{

121 "language": "japanese"

122}

123```

124 

125If your `language` setting is not in the supported list, `/voice` warns you on enable and falls back to English for dictation. Claude's text responses are not affected by this fallback.

126 

127## Rebind the dictation key

128 

129The dictation key is bound to `voice:pushToTalk` in the `Chat` context and defaults to `Space`. The same binding controls both hold and tap modes. Rebind it in [`~/.claude/keybindings.json`](/en/keybindings):

130 

131```json theme={null}

132{

133 "bindings": [

134 {

135 "context": "Chat",

136 "bindings": {

137 "meta+k": "voice:pushToTalk",

138 "space": null

139 }

140 }

141 ]

142}

143```

144 

145Setting `"space": null` removes the default binding. Omit it if you want both keys active.

146 

147In hold mode, avoid binding a bare letter key like `v` since hold detection relies on key-repeat and the letter types into the prompt during warmup. Use `Space`, or use a modifier combination like `meta+k` to start recording on the first keypress with no warmup. Tap mode has no warmup, so any key works. See [customize keyboard shortcuts](/en/keybindings) for the full keybinding syntax.

148 

149## Troubleshooting

150 

151Common issues when voice dictation does not activate or record:

152 

153* **`Voice mode requires a Claude.ai account`**: you are authenticated with an API key or a third-party provider. Run `/login` to sign in with a Claude.ai account.

154* **`Microphone access is denied`**: grant microphone permission to your terminal in system settings. On macOS, go to System Settings → Privacy & Security → Microphone and enable your terminal app, then run `/voice` again. On Windows, go to Settings → Privacy & security → Microphone and turn on microphone access for desktop apps, then run `/voice` again. If your terminal isn't listed in the macOS settings, see [Terminal not listed in macOS Microphone settings](#terminal-not-listed-in-macos-microphone-settings).

155* **`No audio recording tool found` on Linux**: the native audio module could not load and no fallback is installed. Install SoX with the command shown in the error message, for example `sudo apt-get install sox`.

156* **Nothing happens when holding `Space` in hold mode**: watch the prompt input while you hold. If spaces keep accumulating, voice dictation is likely off; run `/voice hold` to enable it. If only one or two spaces appear and then nothing, voice dictation is on but hold detection is not triggering. Hold detection requires your terminal to send key-repeat events, so it cannot detect a held key if key-repeat is disabled at the OS level. Switch to tap mode with `/voice tap` to avoid the key-repeat requirement.

157* **Tapping `Space` types a space instead of recording in tap mode**: the first tap only starts recording when the prompt input is empty. Clear the input first, or check that you are in tap mode by running `/voice tap`.

158* **`No audio detected from microphone`**: recording started but captured silence. Confirm the correct input device is set as the system default and that its input level is not muted or near zero. On Windows, open Settings → System → Sound → Input and select your microphone. On macOS, open System Settings → Sound → Input.

159* **`No speech detected`**: audio reached the transcription service but no words were recognized. Speak closer to the microphone, reduce background noise, and confirm your [dictation language](#change-the-dictation-language) matches the language you are speaking.

160* **Transcription is garbled or in the wrong language**: dictation defaults to English. If you are dictating in another language, set it in `/config` first. See [Change the dictation language](#change-the-dictation-language).

161 

162### Terminal not listed in macOS Microphone settings

163 

164If your terminal app does not appear under System Settings → Privacy & Security → Microphone, there is no toggle you can enable. Reset the permission state for your terminal so the next `/voice` run triggers a fresh macOS permission prompt.

165 

166<Steps>

167 <Step title="Reset the microphone permission for your terminal">

168 Run `tccutil reset Microphone <bundle-id>`, replacing `<bundle-id>` with your terminal's identifier: `com.apple.Terminal` for the built-in Terminal, or `com.googlecode.iterm2` for iTerm2. For other terminals, look up the identifier with `osascript -e 'id of app "AppName"'`.

169 

170 <Warning>

171 You can run `tccutil reset Microphone` without a bundle ID, but it revokes microphone access from every app on your Mac, including apps like Zoom or Slack. Each app will need to re-request access on next use, so don't run it during an active call.

172 </Warning>

173 </Step>

174 

175 <Step title="Quit and relaunch your terminal">

176 macOS won't re-prompt a process that is already running. Quit the terminal app with Cmd+Q, not just close its windows, then open it again.

177 </Step>

178 

179 <Step title="Trigger a fresh prompt">

180 Start Claude Code and run `/voice`. macOS prompts for microphone access; allow it.

181 </Step>

182</Steps>

183 

184## See also

185 

186* [Customize keyboard shortcuts](/en/keybindings): rebind `voice:pushToTalk` and other CLI keyboard actions

187* [Configure settings](/en/settings): full reference for `voice`, `language`, and other settings keys

188* [Interactive mode](/en/interactive-mode): keyboard shortcuts, input modes, and session controls

189* [Commands](/en/commands): reference for `/voice`, `/config`, and all other commands

vs-code.md +131 −54

Details

6 6 

7> Install and configure the Claude Code extension for VS Code. Get AI coding assistance with inline diffs, @-mentions, plan review, and keyboard shortcuts.7> Install and configure the Claude Code extension for VS Code. Get AI coding assistance with inline diffs, @-mentions, plan review, and keyboard shortcuts.

8 8 

9<img src="https://mintcdn.com/claude-code/-YhHHmtSxwr7W8gy/images/vs-code-extension-interface.jpg?fit=max&auto=format&n=-YhHHmtSxwr7W8gy&q=85&s=300652d5678c63905e6b0ea9e50835f8" alt="VS Code editor with the Claude Code extension panel open on the right side, showing a conversation with Claude" data-og-width="2500" width="2500" data-og-height="1155" height="1155" data-path="images/vs-code-extension-interface.jpg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/-YhHHmtSxwr7W8gy/images/vs-code-extension-interface.jpg?w=280&fit=max&auto=format&n=-YhHHmtSxwr7W8gy&q=85&s=87630c671517a3d52e9aee627041696e 280w, https://mintcdn.com/claude-code/-YhHHmtSxwr7W8gy/images/vs-code-extension-interface.jpg?w=560&fit=max&auto=format&n=-YhHHmtSxwr7W8gy&q=85&s=716b093879204beec8d952649ef75292 560w, https://mintcdn.com/claude-code/-YhHHmtSxwr7W8gy/images/vs-code-extension-interface.jpg?w=840&fit=max&auto=format&n=-YhHHmtSxwr7W8gy&q=85&s=c1525d1a01513acd9d83d8b5a8fe2fc8 840w, https://mintcdn.com/claude-code/-YhHHmtSxwr7W8gy/images/vs-code-extension-interface.jpg?w=1100&fit=max&auto=format&n=-YhHHmtSxwr7W8gy&q=85&s=1d90021d58bbb51f871efec13af955c3 1100w, https://mintcdn.com/claude-code/-YhHHmtSxwr7W8gy/images/vs-code-extension-interface.jpg?w=1650&fit=max&auto=format&n=-YhHHmtSxwr7W8gy&q=85&s=7babdd25440099886f193cfa99af88ae 1650w, https://mintcdn.com/claude-code/-YhHHmtSxwr7W8gy/images/vs-code-extension-interface.jpg?w=2500&fit=max&auto=format&n=-YhHHmtSxwr7W8gy&q=85&s=08c92eedfb56fe61a61e480fb63784b6 2500w" />9<img src="https://mintcdn.com/claude-code/-YhHHmtSxwr7W8gy/images/vs-code-extension-interface.jpg?fit=max&auto=format&n=-YhHHmtSxwr7W8gy&q=85&s=300652d5678c63905e6b0ea9e50835f8" alt="VS Code editor with the Claude Code extension panel open on the right side, showing a conversation with Claude" width="2500" height="1155" data-path="images/vs-code-extension-interface.jpg" />

10 10 

11The VS Code extension provides a native graphical interface for Claude Code, integrated directly into your IDE. This is the recommended way to use Claude Code in VS Code.11The VS Code extension provides a native graphical interface for Claude Code, integrated directly into your IDE. This is the recommended way to use Claude Code in VS Code.

12 12 


14 14 

15## Prerequisites15## Prerequisites

16 16 

17Before installing, make sure you have:

18 

17* VS Code 1.98.0 or higher19* VS Code 1.98.0 or higher

18* An Anthropic account (you'll sign in when you first open the extension). If you're using a third-party provider like Amazon Bedrock or Google Vertex AI, see [Use third-party providers](#use-third-party-providers) instead.20* An Anthropic account (you'll sign in when you first open the extension). If you're using a third-party provider like Amazon Bedrock or Google Vertex AI, see [Use third-party providers](#use-third-party-providers) instead.

19 21 


38 40 

39<Steps>41<Steps>

40 <Step title="Open the Claude Code panel">42 <Step title="Open the Claude Code panel">

41 Throughout VS Code, the Spark icon indicates Claude Code: <img src="https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-spark-icon.svg?fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=a734d84e785140016672f08e0abb236c" alt="Spark icon" style={{display: "inline", height: "0.85em", verticalAlign: "middle"}} data-og-width="16" width="16" data-og-height="16" height="16" data-path="images/vs-code-spark-icon.svg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-spark-icon.svg?w=280&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=9a45aad9a84b9fa1701ac99a1f9aa4e9 280w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-spark-icon.svg?w=560&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=3f4cb9254c4d4e93989c4b6bf9292f4b 560w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-spark-icon.svg?w=840&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=e75ccc9faa3e572db8f291ceb65bb264 840w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-spark-icon.svg?w=1100&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=f147bd81a381a62539a4ce361fac41c7 1100w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-spark-icon.svg?w=1650&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=78fe68efaee5d6e844bbacab1b442ed5 1650w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-spark-icon.svg?w=2500&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=efb8dbe1dfa722d094edc6ad2ad4bedb 2500w" />43 Throughout VS Code, the Spark icon indicates Claude Code: <img src="https://mintcdn.com/claude-code/c5r9_6tjPMzFdDDT/images/vs-code-spark-icon.svg?fit=max&auto=format&n=c5r9_6tjPMzFdDDT&q=85&s=3ca45e00deadec8c8f4b4f807da94505" alt="Spark icon" style={{display: "inline", height: "0.85em", verticalAlign: "middle"}} width="16" height="16" data-path="images/vs-code-spark-icon.svg" />

42 44 

43 The quickest way to open Claude is to click the Spark icon in the **Editor Toolbar** (top-right corner of the editor). The icon only appears when you have a file open.45 The quickest way to open Claude is to click the Spark icon in the **Editor Toolbar** (top-right corner of the editor). The icon only appears when you have a file open.

44 46 

45 <img src="https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-editor-icon.png?fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=eb4540325d94664c51776dbbfec4cf02" alt="VS Code editor showing the Spark icon in the Editor Toolbar" data-og-width="2796" width="2796" data-og-height="734" height="734" data-path="images/vs-code-editor-icon.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-editor-icon.png?w=280&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=56f218d5464359d6480cfe23f70a923e 280w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-editor-icon.png?w=560&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=344a8db024b196c795a80dc85cacb8d1 560w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-editor-icon.png?w=840&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=f30bf834ee0625b2a4a635d552d87163 840w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-editor-icon.png?w=1100&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=81fdf984840e43a9f08ae42729d1484d 1100w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-editor-icon.png?w=1650&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=8b60fb32de54717093d512afaa99785c 1650w, https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-editor-icon.png?w=2500&fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=893e6bda8f2e9d42c8a294d394f0b736 2500w" />47 <img src="https://mintcdn.com/claude-code/mfM-EyoZGnQv8JTc/images/vs-code-editor-icon.png?fit=max&auto=format&n=mfM-EyoZGnQv8JTc&q=85&s=eb4540325d94664c51776dbbfec4cf02" alt="VS Code editor showing the Spark icon in the Editor Toolbar" width="2796" height="734" data-path="images/vs-code-editor-icon.png" />

46 48 

47 Other ways to open Claude Code:49 Other ways to open Claude Code:

48 50 

51 * **Activity Bar**: click the Spark icon in the left sidebar to open the sessions list. Click any session to open it as a full editor tab, or start a new one. This icon is always visible in the Activity Bar.

49 * **Command Palette**: `Cmd+Shift+P` (Mac) or `Ctrl+Shift+P` (Windows/Linux), type "Claude Code", and select an option like "Open in New Tab"52 * **Command Palette**: `Cmd+Shift+P` (Mac) or `Ctrl+Shift+P` (Windows/Linux), type "Claude Code", and select an option like "Open in New Tab"

50 * **Status Bar**: Click **✱ Claude Code** in the bottom-right corner of the window. This works even when no file is open.53 * **Status Bar**: click **✱ Claude Code** in the bottom-right corner of the window. This works even when no file is open.

51 54 

52 You can drag the Claude panel to reposition it anywhere in VS Code. See [Customize your workflow](#customize-your-workflow) for details.55 You can drag the Claude panel to reposition it anywhere in VS Code. See [Customize your workflow](#customize-your-workflow) for details.

53 </Step>56 </Step>

54 57 

58 <Step title="Sign in">

59 The first time you open the panel, a sign-in screen appears. Click **Sign in** and complete authorization in your browser.

60 

61 If you see **Not logged in · Please run /login** later, the extension reopens the sign-in screen automatically. If it doesn't appear, reload the window from the Command Palette with **Developer: Reload Window**.

62 

63 If you have `ANTHROPIC_API_KEY` set in your shell but still see the sign-in prompt, VS Code may not have inherited your shell environment. Launch VS Code from a terminal with `code .` so it inherits your environment variables, or sign in with your Claude account instead.

64 

65 After you sign in, a **Learn Claude Code** checklist appears. Work through each item by clicking **Show me**, or dismiss it with the X. To reopen it later, uncheck **Hide Onboarding** in VS Code settings under Extensions → Claude Code.

66 </Step>

67 

55 <Step title="Send a prompt">68 <Step title="Send a prompt">

56 Ask Claude to help with your code or files, whether that's explaining how something works, debugging an issue, or making changes.69 Ask Claude to help with your code or files, whether that's explaining how something works, debugging an issue, or making changes.

57 70 


59 72 

60 Here's an example of asking about a particular line in a file:73 Here's an example of asking about a particular line in a file:

61 74 

62 <img src="https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-send-prompt.png?fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=ede3ed8d8d5f940e01c5de636d009cfd" alt="VS Code editor with lines 2-3 selected in a Python file, and the Claude Code panel showing a question about those lines with an @-mention reference" data-og-width="3288" width="3288" data-og-height="1876" height="1876" data-path="images/vs-code-send-prompt.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-send-prompt.png?w=280&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=f40bde7b2c245fe8f0f5b784e8106492 280w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-send-prompt.png?w=560&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=fad66a27a9a6faa23b05370aa4f398b2 560w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-send-prompt.png?w=840&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=4539c8a3823ca80a5c8771f6c088ce9e 840w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-send-prompt.png?w=1100&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=fae8ebf300c7853409a562ffa46d9c71 1100w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-send-prompt.png?w=1650&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=22e4462bb8cf0c0ca20f8102bc4c971a 1650w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-send-prompt.png?w=2500&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=739bfd045f70fe7be1a109a53494590e 2500w" />75 <img src="https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-send-prompt.png?fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=ede3ed8d8d5f940e01c5de636d009cfd" alt="VS Code editor with lines 2-3 selected in a Python file, and the Claude Code panel showing a question about those lines with an @-mention reference" width="3288" height="1876" data-path="images/vs-code-send-prompt.png" />

63 </Step>76 </Step>

64 77 

65 <Step title="Review changes">78 <Step title="Review changes">

66 When Claude wants to edit a file, it shows a side-by-side comparison of the original and proposed changes, then asks for permission. You can accept, reject, or tell Claude what to do instead.79 When Claude wants to edit a file, it shows a side-by-side comparison of the original and proposed changes, then asks for permission. You can accept, reject, or tell Claude what to do instead. If you edit the proposed content directly in the diff view before accepting, Claude is told that you modified it so it does not assume the file matches its original proposal.

67 80 

68 <img src="https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-edits.png?fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=e005f9b41c541c5c7c59c082f7c4841c" alt="VS Code showing a diff of Claude's proposed changes with a permission prompt asking whether to make the edit" data-og-width="3292" width="3292" data-og-height="1876" height="1876" data-path="images/vs-code-edits.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-edits.png?w=280&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=cb5d41b81087f79b842a56b5a3304660 280w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-edits.png?w=560&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=90bb691960decdc06393c3c21cd62c75 560w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-edits.png?w=840&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=9a11bf878ba619e850380904ff4f38e8 840w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-edits.png?w=1100&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=6dddbf596b4f69ec6245bdc5eb6dd487 1100w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-edits.png?w=1650&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=ef2713b8cbfd2cee97af817d813d64c7 1650w, https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-edits.png?w=2500&fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=1f7e1c52919cdfddf295f32a2ec7ae59 2500w" />81 <img src="https://mintcdn.com/claude-code/FVYz38sRY-VuoGHA/images/vs-code-edits.png?fit=max&auto=format&n=FVYz38sRY-VuoGHA&q=85&s=e005f9b41c541c5c7c59c082f7c4841c" alt="VS Code showing a diff of Claude's proposed changes with a permission prompt asking whether to make the edit" width="3292" height="1876" data-path="images/vs-code-edits.png" />

69 </Step>82 </Step>

70</Steps>83</Steps>

71 84 

72For more ideas on what you can do with Claude Code, see [Common workflows](/en/common-workflows).85For more ideas on what you can do with Claude Code, see [Common workflows](/en/common-workflows).

73 86 

74<Tip>87<Tip>

75 The extension includes two built-in tutorials:88 Run "Claude Code: Open Walkthrough" from the Command Palette for a guided tour of the basics.

76 

77 * **VS Code walkthrough**: Run "Claude Code: Open Walkthrough" from the Command Palette for a guided tour of the basics.

78 * **Interactive checklist**: Click the graduation cap icon in the Claude panel header to work through features like writing code, using Plan mode, and setting up rules.

79</Tip>89</Tip>

80 90 

81## Use the prompt box91## Use the prompt box

82 92 

83The prompt box supports several features:93The prompt box supports several features:

84 94 

85* **Permission modes**: Click the mode indicator at the bottom of the prompt box to switch modes. In normal mode, Claude asks permission before each action. In Plan mode, Claude describes what it will do and waits for approval before making changes. In auto-accept mode, Claude makes edits without asking. Set the default in VS Code settings under `claudeCode.initialPermissionMode`.95* **Permission modes**: click the mode indicator at the bottom of the prompt box to switch modes. In normal mode, Claude asks permission before each action. In Plan mode, Claude describes what it will do and waits for approval before making changes. VS Code automatically opens the plan as a full markdown document where you can add inline comments to give feedback before Claude begins. In auto-accept mode, Claude makes edits without asking. Set the default in VS Code settings under `claudeCode.initialPermissionMode`.

86* **Command menu**: Click `/` or type `/` to open the command menu. Options include attaching files, switching models, toggling extended thinking, and viewing plan usage (`/usage`). The Customize section provides access to MCP servers, hooks, memory, permissions, and plugins. Items with a terminal icon open in the integrated terminal.96* **Command menu**: click `/` or type `/` to open the command menu. Options include attaching files, switching models, toggling extended thinking, viewing plan usage (`/usage`), and starting a [Remote Control](/en/remote-control) session (`/remote-control`). The Customize section provides access to MCP servers, hooks, memory, permissions, and plugins. Items with a terminal icon open in the integrated terminal.

87* **Context indicator**: The prompt box shows how much of Claude's context window you're using. Claude automatically compacts when needed, or you can run `/compact` manually.97* **Context indicator**: the prompt box shows how much of Claude's context window you're using. Claude automatically compacts when needed, or you can run `/compact` manually.

88* **Extended thinking**: Lets Claude spend more time reasoning through complex problems. Toggle it on via the command menu (`/`). See [Extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) for details.98* **Extended thinking**: lets Claude spend more time reasoning through complex problems. Toggle it on via the command menu (`/`). Claude's reasoning appears in the conversation as collapsed blocks: click a block to read it, or press `Ctrl+O` to expand or collapse every thinking block in the session. See [Extended thinking](/en/common-workflows#use-extended-thinking-thinking-mode) for details.

89* **Multi-line input**: Press `Shift+Enter` to add a new line without sending.99* **Multi-line input**: press `Shift+Enter` to add a new line without sending. This also works in the "Other" free-text input of question dialogs.

90 100 

91### Reference files and folders101### Reference files and folders

92 102 

93Use @-mentions to give Claude context about specific files or folders. When you type `@` followed by a file or folder name, Claude reads that content and can answer questions about it or make changes to it. Claude Code supports fuzzy matching, so you can type partial names to find what you need:103Use @-mentions to give Claude context about specific files or folders. When you type `@` followed by a file or folder name, Claude reads that content and can answer questions about it or make changes to it. Claude Code supports fuzzy matching, so you can type partial names to find what you need:

94 104 

95```105```text theme={null}

96> Explain the logic in @auth (fuzzy matches auth.js, AuthService.ts, etc.)106> Explain the logic in @auth (fuzzy matches auth.js, AuthService.ts, etc.)

97> What's in @src/components/ (include a trailing slash for folders)107> What's in @src/components/ (include a trailing slash for folders)

98```108```

99 109 

110For large PDFs, you can ask Claude to read specific pages instead of the whole file: a single page, a range like pages 1-10, or an open-ended range like page 3 onward.

111 

100When you select text in the editor, Claude can see your highlighted code automatically. The prompt box footer shows how many lines are selected. Press `Option+K` (Mac) / `Alt+K` (Windows/Linux) to insert an @-mention with the file path and line numbers (e.g., `@app.ts#5-10`). Click the selection indicator to toggle whether Claude can see your highlighted text - the eye-slash icon means the selection is hidden from Claude.112When you select text in the editor, Claude can see your highlighted code automatically. The prompt box footer shows how many lines are selected. Press `Option+K` (Mac) / `Alt+K` (Windows/Linux) to insert an @-mention with the file path and line numbers (e.g., `@app.ts#5-10`). Click the selection indicator to toggle whether Claude can see your highlighted text - the eye-slash icon means the selection is hidden from Claude.

101 113 

102You can also hold `Shift` while dragging files into the prompt box to add them as attachments. Click the X on any attachment to remove it from context.114You can also hold `Shift` while dragging files into the prompt box to add them as attachments. Click the X on any attachment to remove it from context.

103 115 

104### Resume past conversations116### Resume past conversations

105 117 

106Click the dropdown at the top of the Claude Code panel to access your conversation history. You can search by keyword or browse by time (Today, Yesterday, Last 7 days, etc.). Click any conversation to resume it with the full message history. For more on resuming sessions, see [Common workflows](/en/common-workflows#resume-previous-conversations).118Click the **Session history** button at the top of the Claude Code panel to access your conversation history. You can search by keyword or browse by time (Today, Yesterday, Last 7 days, etc.). Click any conversation to resume it with the full message history. New sessions receive AI-generated titles based on your first message. Hover over a session to reveal rename and remove actions: rename to give it a descriptive title, or remove to delete it from the list. For more on resuming sessions, see [Common workflows](/en/common-workflows#resume-previous-conversations).

107 119 

108### Resume remote sessions from Claude.ai120### Resume remote sessions from Claude.ai

109 121 

110If you use [Claude Code on the web](/en/claude-code-on-the-web), you can resume those remote sessions directly in VS Code. This requires signing in with **Claude.ai Subscription**, not Anthropic Console.122If you use [Claude Code on the web](/en/claude-code-on-the-web), you can resume those remote sessions directly in VS Code. This requires signing in with **Claude.ai Subscription**, not Anthropic Console.

111 123 

112<Steps>124<Steps>

113 <Step title="Open Past Conversations">125 <Step title="Open session history">

114 Click the **Past Conversations** dropdown at the top of the Claude Code panel.126 Click the **Session history** button at the top of the Claude Code panel.

115 </Step>127 </Step>

116 128 

117 <Step title="Select the Remote tab">129 <Step title="Select the Remote tab">


135 147 

136You can drag the Claude panel to reposition it anywhere in VS Code. Grab the panel's tab or title bar and drag it to:148You can drag the Claude panel to reposition it anywhere in VS Code. Grab the panel's tab or title bar and drag it to:

137 149 

138* **Secondary sidebar**: The right side of the window. Keeps Claude visible while you code.150* **Secondary sidebar**: the right side of the window. Keeps Claude visible while you code.

139* **Primary sidebar**: The left sidebar with icons for Explorer, Search, etc.151* **Primary sidebar**: the left sidebar with icons for Explorer, Search, etc.

140* **Editor area**: Opens Claude as a tab alongside your files. Useful for side tasks.152* **Editor area**: opens Claude as a tab alongside your files. Useful for side tasks.

141 153 

142<Tip>154<Tip>

143 Use the sidebar for your main Claude session and open additional tabs for side tasks. Claude remembers your preferred location. Note that the Spark icon only appears in the Activity Bar when the Claude panel is docked to the left. Since Claude defaults to the right side, use the Editor Toolbar icon to open Claude.155 Use the sidebar for your main Claude session and open additional tabs for side tasks. Claude remembers your preferred location. The Activity Bar sessions list icon is separate from the Claude panel: the sessions list is always visible in the Activity Bar, while the Claude panel icon only appears there when the panel is docked to the left sidebar.

144</Tip>156</Tip>

145 157 

146### Run multiple conversations158### Run multiple conversations


172 184 

173When you install a plugin, choose the installation scope:185When you install a plugin, choose the installation scope:

174 186 

175* **Install for you**: Available in all your projects (user scope)187* **Install for you**: available in all your projects (user scope)

176* **Install for this project**: Shared with project collaborators (project scope)188* **Install for this project**: shared with project collaborators (project scope)

177* **Install locally**: Only for you, only in this repository (local scope)189* **Install locally**: only for you, only in this repository (local scope)

178 190 

179### Manage marketplaces191### Manage marketplaces

180 192 


192 204 

193For more about the plugin system, see [Plugins](/en/plugins) and [Plugin marketplaces](/en/plugin-marketplaces).205For more about the plugin system, see [Plugins](/en/plugins) and [Plugin marketplaces](/en/plugin-marketplaces).

194 206 

207## Automate browser tasks with Chrome

208 

209Connect Claude to your Chrome browser to test web apps, debug with console logs, and automate browser workflows without leaving VS Code. This requires the [Claude in Chrome extension](https://chromewebstore.google.com/detail/claude/fcoeoabgfenejglbffodgkkbkcdhcgfn) version 1.0.36 or higher.

210 

211Type `@browser` in the prompt box followed by what you want Claude to do:

212 

213```text theme={null}

214@browser go to localhost:3000 and check the console for errors

215```

216 

217You can also open the attachment menu to select specific browser tools like opening a new tab or reading page content.

218 

219Claude opens new tabs for browser tasks and shares your browser's login state, so it can access any site you're already signed into.

220 

221For setup instructions, the full list of capabilities, and troubleshooting, see [Use Claude Code with Chrome](/en/chrome).

222 

195## VS Code commands and shortcuts223## VS Code commands and shortcuts

196 224 

197Open the Command Palette (`Cmd+Shift+P` on Mac or `Ctrl+Shift+P` on Windows/Linux) and type "Claude Code" to see all available VS Code commands for the Claude Code extension.225Open the Command Palette (`Cmd+Shift+P` on Mac or `Ctrl+Shift+P` on Windows/Linux) and type "Claude Code" to see all available VS Code commands for the Claude Code extension.


203</Note>231</Note>

204 232 

205| Command | Shortcut | Description |233| Command | Shortcut | Description |

206| -------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------ |234| -------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |

207| Focus Input | `Cmd+Esc` (Mac) / `Ctrl+Esc` (Windows/Linux) | Toggle focus between editor and Claude |235| Focus Input | `Cmd+Esc` (Mac) / `Ctrl+Esc` (Windows/Linux) | Toggle focus between editor and Claude |

208| Open in Side Bar | - | Open Claude in the left sidebar |236| Open in Side Bar | - | Open Claude in the left sidebar |

209| Open in Terminal | - | Open Claude in terminal mode |237| Open in Terminal | - | Open Claude in terminal mode |

210| Open in New Tab | `Cmd+Shift+Esc` (Mac) / `Ctrl+Shift+Esc` (Windows/Linux) | Open a new conversation as an editor tab |238| Open in New Tab | `Cmd+Shift+Esc` (Mac) / `Ctrl+Shift+Esc` (Windows/Linux) | Open a new conversation as an editor tab |

211| Open in New Window | - | Open a new conversation in a separate window |239| Open in New Window | - | Open a new conversation in a separate window |

212| New Conversation | `Cmd+N` (Mac) / `Ctrl+N` (Windows/Linux) | Start a new conversation (requires Claude to be focused) |240| New Conversation | `Cmd+N` (Mac) / `Ctrl+N` (Windows/Linux) | Start a new conversation. Requires Claude to be focused and `enableNewConversationShortcut` set to `true` |

213| Insert @-Mention Reference | `Option+K` (Mac) / `Alt+K` (Windows/Linux) | Insert a reference to the current file and selection (requires editor to be focused) |241| Insert @-Mention Reference | `Option+K` (Mac) / `Alt+K` (Windows/Linux) | Insert a reference to the current file and selection (requires editor to be focused) |

214| Show Logs | - | View extension debug logs |242| Show Logs | - | View extension debug logs |

215| Logout | - | Sign out of your Anthropic account |243| Logout | - | Sign out of your Anthropic account |

216 244 

245### Launch a VS Code tab from other tools

246 

247The extension registers a URI handler at `vscode://anthropic.claude-code/open`. Use it to open a new Claude Code tab from your own tooling: a shell alias, a browser bookmarklet, or any script that can open a URL. If VS Code isn't already running, opening the URL launches it first. If VS Code is already running, the URL opens in whichever window is currently focused.

248 

249Invoke the handler with your operating system's URL opener. On macOS:

250 

251```bash theme={null}

252open "vscode://anthropic.claude-code/open"

253```

254 

255Use `xdg-open` on Linux or `start` on Windows.

256 

257The handler accepts two optional query parameters:

258 

259| Parameter | Description |

260| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

261| `prompt` | Text to pre-fill in the prompt box. Must be URL-encoded. The prompt is pre-filled but not submitted automatically. |

262| `session` | A session ID to resume instead of starting a new conversation. The session must belong to the workspace currently open in VS Code. If the session isn't found, a fresh conversation starts instead. If the session is already open in a tab, that tab is focused. To capture a session ID programmatically, see [Continue conversations](/en/headless#continue-conversations). |

263 

264For example, to open a tab pre-filled with "review my changes":

265 

266```text theme={null}

267vscode://anthropic.claude-code/open?prompt=review%20my%20changes

268```

269 

217## Configure settings270## Configure settings

218 271 

219The extension has two types of settings:272The extension has two types of settings:

220 273 

221* **Extension settings** in VS Code: Control the extension's behavior within VS Code. Open with `Cmd+,` (Mac) or `Ctrl+,` (Windows/Linux), then go to Extensions → Claude Code. You can also type `/` and select **General Config** to open settings.274* **Extension settings** in VS Code: control the extension's behavior within VS Code. Open with `Cmd+,` (Mac) or `Ctrl+,` (Windows/Linux), then go to Extensions → Claude Code. You can also type `/` and select **General Config** to open settings.

222* **Claude Code settings** in `~/.claude/settings.json`: Shared between the extension and CLI. Use for allowed commands, environment variables, hooks, and MCP servers. See [Settings](/en/settings) for details.275* **Claude Code settings** in `~/.claude/settings.json`: shared between the extension and CLI. Use for allowed commands, environment variables, hooks, and MCP servers. See [Settings](/en/settings) for details.

276 

277<Tip>

278 Add `"$schema": "https://json.schemastore.org/claude-code-settings.json"` to your `settings.json` to get autocomplete and inline validation for all available settings directly in VS Code.

279</Tip>

223 280 

224### Extension settings281### Extension settings

225 282 

226| Setting | Default | Description |283| Setting | Default | Description |

227| --------------------------------- | --------- | ----------------------------------------------------------------------------------------------------- |284| --------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

228| `selectedModel` | `default` | Model for new conversations. Change per-session with `/model`. |

229| `useTerminal` | `false` | Launch Claude in terminal mode instead of graphical panel |285| `useTerminal` | `false` | Launch Claude in terminal mode instead of graphical panel |

230| `initialPermissionMode` | `default` | Controls approval prompts: `default` (ask each time), `plan`, `acceptEdits`, or `bypassPermissions` |286| `initialPermissionMode` | `default` | Controls approval prompts for new conversations: `default`, `plan`, `acceptEdits`, or `bypassPermissions`. See [permission modes](/en/permission-modes). |

231| `preferredLocation` | `panel` | Where Claude opens: `sidebar` (right) or `panel` (new tab) |287| `preferredLocation` | `panel` | Where Claude opens: `sidebar` (right) or `panel` (new tab) |

232| `autosave` | `true` | Auto-save files before Claude reads or writes them |288| `autosave` | `true` | Auto-save files before Claude reads or writes them |

233| `useCtrlEnterToSend` | `false` | Use Ctrl/Cmd+Enter instead of Enter to send prompts |289| `useCtrlEnterToSend` | `false` | Use Ctrl/Cmd+Enter instead of Enter to send prompts |

234| `enableNewConversationShortcut` | `true` | Enable Cmd/Ctrl+N to start a new conversation |290| `enableNewConversationShortcut` | `false` | Enable Cmd/Ctrl+N to start a new conversation |

235| `hideOnboarding` | `false` | Hide the onboarding checklist (graduation cap icon) |291| `hideOnboarding` | `false` | Hide the onboarding checklist (graduation cap icon) |

236| `respectGitIgnore` | `true` | Exclude .gitignore patterns from file searches |292| `respectGitIgnore` | `true` | Exclude .gitignore patterns from file searches |

293| `usePythonEnvironment` | `true` | Activate the workspace's Python environment when running Claude. Requires the Python extension. |

237| `environmentVariables` | `[]` | Set environment variables for the Claude process. Use Claude Code settings instead for shared config. |294| `environmentVariables` | `[]` | Set environment variables for the Claude process. Use Claude Code settings instead for shared config. |

238| `disableLoginPrompt` | `false` | Skip authentication prompts (for third-party provider setups) |295| `disableLoginPrompt` | `false` | Skip authentication prompts (for third-party provider setups) |

239| `allowDangerouslySkipPermissions` | `false` | Bypass all permission prompts. **Use with extreme caution.** |296| `allowDangerouslySkipPermissions` | `false` | Adds [Auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) and Bypass permissions to the mode selector. Auto mode has [plan, admin, model, and provider requirements](/en/permission-modes#eliminate-prompts-with-auto-mode), so it may remain unavailable even with this toggle on. Use Bypass permissions only in sandboxes with no internet access. |

240| `claudeProcessWrapper` | - | Executable path used to launch the Claude process |297| `claudeProcessWrapper` | - | Executable path used to launch the Claude process |

241 298 

242## VS Code extension vs. Claude Code CLI299## VS Code extension vs. Claude Code CLI


244Claude Code is available as both a VS Code extension (graphical panel) and a CLI (command-line interface in the terminal). Some features are only available in the CLI. If you need a CLI-only feature, run `claude` in VS Code's integrated terminal.301Claude Code is available as both a VS Code extension (graphical panel) and a CLI (command-line interface in the terminal). Some features are only available in the CLI. If you need a CLI-only feature, run `claude` in VS Code's integrated terminal.

245 302 

246| Feature | CLI | VS Code Extension |303| Feature | CLI | VS Code Extension |

247| ------------------- | --------------------------------------------- | ---------------------------------------- |304| ------------------- | ------------------- | ------------------------------------------------------------------------------------ |

248| Commands and skills | [All](/en/interactive-mode#built-in-commands) | Subset (type `/` to see available) |305| Commands and skills | [All](/en/commands) | Subset (type `/` to see available) |

249| MCP server config | Yes | No (configure via CLI, use in extension) |306| MCP server config | Yes | Partial (add servers via CLI; manage existing servers with `/mcp` in the chat panel) |

250| Checkpoints | Yes | Yes |307| Checkpoints | Yes | Yes |

251| `!` bash shortcut | Yes | No |308| `!` bash shortcut | Yes | No |

252| Tab completion | Yes | No |309| Tab completion | Yes | No |


281 338 

282### Connect to external tools with MCP339### Connect to external tools with MCP

283 340 

284MCP (Model Context Protocol) servers give Claude access to external tools, databases, and APIs. Configure them via CLI, then use them in both extension and CLI.341MCP (Model Context Protocol) servers give Claude access to external tools, databases, and APIs.

285 342 

286To add an MCP server, open the integrated terminal (`` Ctrl+` `` or `` Cmd+` ``) and run:343To add an MCP server, open the integrated terminal (`` Ctrl+` `` or `` Cmd+` ``) and run `claude mcp add`. The example below adds GitHub's remote MCP server, which authenticates with a [personal access token](https://github.com/settings/personal-access-tokens) passed as a header:

287 344 

288```bash theme={null}345```bash theme={null}

289claude mcp add --transport http github https://api.githubcopilot.com/mcp/346claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \

347 --header "Authorization: Bearer YOUR_GITHUB_PAT"

290```348```

291 349 

292Once configured, ask Claude to use the tools (e.g., "Review PR #456"). Some servers require authentication: run `claude` in the terminal, then type `/mcp` to authenticate. See the [MCP documentation](/en/mcp) for available servers.350Once configured, ask Claude to use the tools (e.g., "Review PR #456").

351 

352To manage MCP servers without leaving VS Code, type `/mcp` in the chat panel. The MCP management dialog lets you enable or disable servers, reconnect to a server, and manage OAuth authentication. See the [MCP documentation](/en/mcp) for available servers.

293 353 

294## Work with git354## Work with git

295 355 


299 359 

300Claude can stage changes, write commit messages, and create pull requests based on your work:360Claude can stage changes, write commit messages, and create pull requests based on your work:

301 361 

302```362```text theme={null}

303> commit my changes with a descriptive message363> commit my changes with a descriptive message

304> create a pr for this feature364> create a pr for this feature

305> summarize the changes I've made to the auth module365> summarize the changes I've made to the auth module


309 369 

310### Use git worktrees for parallel tasks370### Use git worktrees for parallel tasks

311 371 

312Git worktrees allow multiple Claude Code sessions to work on separate branches simultaneously, each with isolated files:372Use the `--worktree` (`-w`) flag to start Claude in an isolated worktree with its own files and branch:

313 373 

314```bash theme={null}374```bash theme={null}

315# Create a worktree for a new feature375claude --worktree feature-auth

316git worktree add ../project-feature-a -b feature-a

317 

318# Run Claude Code in each worktree

319cd ../project-feature-a && claude

320```376```

321 377 

322Each worktree maintains independent file state while sharing git history. This prevents Claude instances from interfering with each other when working on different tasks.378Each worktree maintains independent file state while sharing git history. This prevents Claude instances from interfering with each other when working on different tasks. For more details, see [Run parallel sessions with Git worktrees](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees).

323 

324For detailed git workflows including PR reviews and branch management, see [Common workflows](/en/common-workflows#create-pull-requests).

325 379 

326## Use third-party providers380## Use third-party providers

327 381 


355* Use manual approval mode instead of auto-accept for edits409* Use manual approval mode instead of auto-accept for edits

356* Review changes carefully before accepting them410* Review changes carefully before accepting them

357 411 

412### The built-in IDE MCP server

413 

414When the extension is active, it runs a local MCP server that the CLI connects to automatically. This is how the CLI opens diffs in VS Code's native diff viewer, reads your current selection for `@`-mentions, and — when you're working in a Jupyter notebook — asks VS Code to execute cells.

415 

416The server is named `ide` and is hidden from `/mcp` because there's nothing to configure. If your organization uses a `PreToolUse` hook to allowlist MCP tools, though, you'll need to know it exists.

417 

418**Transport and authentication.** The server binds to `127.0.0.1` on a random high port and is not reachable from other machines. Each extension activation generates a fresh random auth token that the CLI must present to connect. The token is written to a lock file under `~/.claude/ide/` with `0600` permissions in a `0700` directory, so only the user running VS Code can read it.

419 

420**Tools exposed to the model.** The server hosts a dozen tools, but only two are visible to the model. The rest are internal RPC the CLI uses for its own UI — opening diffs, reading selections, saving files — and are filtered out before the tool list reaches Claude.

421 

422| Tool name (as seen by hooks) | What it does | Writes? |

423| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------- |

424| `mcp__ide__getDiagnostics` | Returns language-server diagnostics — the errors and warnings in VS Code's Problems panel. Optionally scoped to one file. | No |

425| `mcp__ide__executeCode` | Runs Python code in the active Jupyter notebook's kernel. See confirmation flow below. | Yes |

426 

427**Jupyter execution always asks first.** `mcp__ide__executeCode` can't run anything silently. On each call, the code is inserted as a new cell at the end of the active notebook, VS Code scrolls it into view, and a native Quick Pick asks you to **Execute** or **Cancel**. Cancelling — or dismissing the picker with `Esc` — returns an error to Claude and nothing runs. The tool also refuses outright when there's no active notebook, when the Jupyter extension (`ms-toolsai.jupyter`) isn't installed, or when the kernel isn't Python.

428 

429<Note>

430 The Quick Pick confirmation is separate from `PreToolUse` hooks. An allowlist entry for `mcp__ide__executeCode` lets Claude *propose* running a cell; the Quick Pick inside VS Code is what lets it *actually* run.

431</Note>

432 

433<a id="troubleshooting" />

434 

358## Fix common issues435## Fix common issues

359 436 

360### Extension won't install437### Extension won't install


406Now that you have Claude Code set up in VS Code:483Now that you have Claude Code set up in VS Code:

407 484 

408* [Explore common workflows](/en/common-workflows) to get the most out of Claude Code485* [Explore common workflows](/en/common-workflows) to get the most out of Claude Code

409* [Set up MCP servers](/en/mcp) to extend Claude's capabilities with external tools. Configure servers using the CLI, then use them in the extension.486* [Set up MCP servers](/en/mcp) to extend Claude's capabilities with external tools. Add servers using the CLI, then manage them with `/mcp` in the chat panel.

410* [Configure Claude Code settings](/en/settings) to customize allowed commands, hooks, and more. These settings are shared between the extension and CLI.487* [Configure Claude Code settings](/en/settings) to customize allowed commands, hooks, and more. These settings are shared between the extension and CLI.

web-quickstart.md +220 −0 added

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# Get started with Claude Code on the web

6 

7> Run Claude Code in the cloud from your browser or phone. Connect a GitHub repository, submit a task, and review the PR without local setup.

8 

9<Note>

10 Claude Code on the web is in research preview for Pro, Max, and Team users, and for Enterprise users with premium seats or Chat + Claude Code seats.

11</Note>

12 

13Claude Code on the web runs on Anthropic-managed cloud infrastructure instead of your machine. Submit tasks from [claude.ai/code](https://claude.ai/code) in your browser or the Claude mobile app.

14 

15You'll need a GitHub repository to [get started](#connect-github-and-create-an-environment). Claude clones it into an isolated virtual machine, makes changes, and pushes a branch for you to review. Sessions persist across devices, so a task you start on your laptop is ready to review from your phone later.

16 

17Claude Code on the web works well for:

18 

19* **Parallel tasks**: run several independent tasks at once, each in its own session and branch, without managing multiple worktrees

20* **Repos you don't have locally**: Claude clones the repo fresh every session, so you don't need it checked out

21* **Tasks that don't need frequent steering**: submit a well-defined task, do something else, and review the result when Claude is done

22* **Code questions and exploration**: understand a codebase or trace how a feature is implemented without a local checkout

23 

24For work that needs your local config, tools, or environment, running Claude Code locally or using [Remote Control](/en/remote-control) is a better fit.

25 

26## How sessions run

27 

28When you submit a task:

29 

301. **Clone and prepare**: your repository is cloned to an Anthropic-managed VM, and your [setup script](/en/claude-code-on-the-web#setup-scripts) runs if configured.

312. **Configure network**: internet access is set based on your environment's [access level](/en/claude-code-on-the-web#access-levels).

323. **Work**: Claude analyzes code, makes changes, runs tests, and checks its work. You can watch and steer throughout, or step away and come back when it's done.

334. **Push the branch**: when Claude reaches a stopping point, it pushes its branch to GitHub. You review the diff, leave inline comments, create a PR, or send another message to keep going.

34 

35The session doesn't close when the branch is pushed. PR creation and further edits all happen within the same conversation.

36 

37## Compare ways to run Claude Code

38 

39Claude Code behaves the same everywhere. What changes is where code executes and whether your local config is available. The Desktop app offers both local and cloud sessions, so its answers below depend on which you choose:

40 

41| | On the web | Remote Control | Terminal CLI | Desktop app |

42| :------------------------------------------- | :-------------------------------------------------------------------------------------------------------------- | :--------------------------- | :--------------------- | :-------------------------- |

43| **Code runs on** | Anthropic cloud VM | Your machine | Your machine | Your machine or cloud VM |

44| **You chat from** | claude.ai or mobile app | claude.ai or mobile app | Your terminal | The Desktop UI |

45| **Uses your local config** | No, repo only | Yes | Yes | Yes for local, no for cloud |

46| **Requires GitHub** | Yes, or [bundle a local repo](/en/claude-code-on-the-web#send-local-repositories-without-github) via `--remote` | No | No | Only for cloud sessions |

47| **Keeps running if you disconnect** | Yes | While terminal stays open | No | Depends on session type |

48| **[Permission modes](/en/permission-modes)** | Auto accept edits, Plan | Ask, Auto accept edits, Plan | All modes | Depends on session type |

49| **Network access** | Configurable per environment | Your machine's network | Your machine's network | Depends on session type |

50 

51See the [terminal quickstart](/en/quickstart), [Desktop app](/en/desktop), or [Remote Control](/en/remote-control) docs to set those up.

52 

53## Connect GitHub and create an environment

54 

55Setup is a one-time process. If you already use the GitHub CLI, you can [do this from your terminal](#connect-from-your-terminal) instead of the browser.

56 

57<Steps>

58 <Step title="Visit claude.ai/code">

59 Go to [claude.ai/code](https://claude.ai/code) and sign in with your Anthropic account.

60 </Step>

61 

62 <Step title="Install the Claude GitHub App">

63 After signing in, claude.ai/code prompts you to connect GitHub. Follow the prompt to install the Claude GitHub App and grant it access to your repositories. Cloud sessions work with existing GitHub repositories, so to start a new project, [create an empty repository on GitHub](https://github.com/new) first.

64 </Step>

65 

66 <Step title="Create your environment">

67 After connecting GitHub, you'll be prompted to create a cloud environment. The environment controls what network access Claude has during sessions and what runs when a new session is created. See [Installed tools](/en/claude-code-on-the-web#installed-tools) for what's available without any configuration.

68 

69 The form has these fields:

70 

71 * **Name**: a display label. Useful when you have multiple environments for different projects or access levels.

72 * **Network access**: controls what the session can reach on the internet. The default, `Trusted`, allows connections to [common package registries](/en/claude-code-on-the-web#default-allowed-domains) like npm, PyPI, and RubyGems while blocking general internet access.

73 * **Environment variables**: optional variables available in every session, in `.env` format. Don't wrap values in quotes, since quotes are stored as part of the value. These are visible to anyone who can edit this environment.

74 * **Setup script**: an optional Bash script that runs before Claude Code launches. Use it to install system tools the cloud VM doesn't include, like `apt install -y gh`. The result is [cached](/en/claude-code-on-the-web#environment-caching), so the script doesn't re-run on every session. See [Setup scripts](/en/claude-code-on-the-web#setup-scripts) for examples and debugging tips.

75 

76 For a first project, leave the defaults and click **Create environment**. You can [edit it later or create additional environments](/en/claude-code-on-the-web#configure-your-environment) for different projects.

77 </Step>

78</Steps>

79 

80### Connect from your terminal

81 

82If you already use the GitHub CLI (`gh`), you can set up Claude Code on the web without opening a browser. This requires the [Claude Code CLI](/en/quickstart). `/web-setup` reads your local `gh` token, links it to your Claude account, and creates a default cloud environment if you don't have one.

83 

84<Note>

85 Organizations with [Zero Data Retention](/en/zero-data-retention) enabled cannot use `/web-setup` or other cloud session features. If the GitHub CLI isn't installed or authenticated, `/web-setup` opens the browser onboarding flow instead.

86</Note>

87 

88<Steps>

89 <Step title="Authenticate with the GitHub CLI">

90 In your shell, authenticate the GitHub CLI if you haven't already:

91 

92 ```bash theme={null}

93 gh auth login

94 ```

95 </Step>

96 

97 <Step title="Sign in to Claude">

98 In the Claude Code CLI, run `/login` to sign in with your claude.ai account. Skip this step if you're already signed in.

99 </Step>

100 

101 <Step title="Run /web-setup">

102 In the Claude Code CLI, run:

103 

104 ```text theme={null}

105 /web-setup

106 ```

107 

108 This syncs your `gh` token to your Claude account. If you don't have a cloud environment yet, `/web-setup` creates one with Trusted network access and no setup script. You can [edit the environment or add variables](/en/claude-code-on-the-web#configure-your-environment) afterward. Once `/web-setup` completes, you can start cloud sessions from your terminal with [`--remote`](/en/claude-code-on-the-web#from-terminal-to-web) or set up recurring tasks with [`/schedule`](/en/routines).

109 </Step>

110</Steps>

111 

112## Start a task

113 

114With GitHub connected and an environment created, you're ready to submit tasks.

115 

116<Steps>

117 <Step title="Select a repository and branch">

118 From [claude.ai/code](https://claude.ai/code) or the Code tab in the Claude mobile app, click the repository selector below the input box and choose a repository for Claude to work in. Each repository shows a branch selector. Change it to start Claude from a feature branch instead of the default. You can add multiple repositories to work across them in one session.

119 </Step>

120 

121 <Step title="Choose a permission mode">

122 The mode dropdown next to the input defaults to **Auto accept edits**, where Claude makes changes and pushes a branch without stopping for approval. Switch to **Plan mode** if you want Claude to propose an approach and wait for your go-ahead before editing files. Cloud sessions don't offer Ask permissions, Auto mode, or Bypass permissions. See [Permission modes](/en/permission-modes) for the full list.

123 </Step>

124 

125 <Step title="Describe the task and submit">

126 Type a description of what you want and press Enter. Be specific:

127 

128 * Name the file or function: "Add a README with setup instructions" or "Fix the failing auth test in `tests/test_auth.py`" is better than "fix tests"

129 * Paste error output if you have it

130 * Describe the expected behavior, not just the symptom

131 

132 Claude clones the repositories, runs your setup script if configured, and starts working. Each task gets its own session and its own branch, so you don't need to wait for one to finish before starting another.

133 </Step>

134</Steps>

135 

136## Pre-fill sessions

137 

138You can prefill the prompt, repositories, and environment for a new session by adding query parameters to the [claude.ai/code](https://claude.ai/code) URL. Use this to build integrations such as a button in your issue tracker that opens Claude Code with the issue description as the prompt.

139 

140| Parameter | Description |

141| :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |

142| `prompt` | Prompt text to prefill in the input box. The alias `q` is also accepted. |

143| `prompt_url` | URL to fetch the prompt text from, for prompts too long to embed in a query string. The URL must allow cross-origin requests. Ignored when `prompt` is also set. |

144| `repositories` | Comma-separated list of `owner/repo` slugs to preselect. The alias `repo` is also accepted. |

145| `environment` | Name or ID of the [environment](#connect-github-and-create-an-environment) to preselect. |

146 

147URL-encode each value. The example below opens the form with a prompt and a repository already selected:

148 

149```text theme={null}

150https://claude.ai/code?prompt=Fix%20the%20login%20bug&repositories=acme/webapp

151```

152 

153## Review and iterate

154 

155When Claude finishes, review the changes, leave feedback on specific lines, and keep going until the diff looks right.

156 

157<Steps>

158 <Step title="Open the diff view">

159 A diff indicator shows lines added and removed across the session, for example `+42 -18`. Select it to open the diff view, with a file list on the left and changes on the right.

160 </Step>

161 

162 <Step title="Leave inline comments">

163 Select any line in the diff, type your feedback, and press Enter. Comments queue up until you send your next message, then they're bundled with it. Claude sees "at `src/auth.ts:47`, don't catch the error here" alongside your main instruction, so you don't have to describe where the problem is.

164 </Step>

165 

166 <Step title="Create a pull request">

167 When the diff looks right, select **Create PR** at the top of the diff view. You can open it as a full PR, a draft, or jump to GitHub's compose page with a generated title and description.

168 </Step>

169 

170 <Step title="Keep iterating after the PR">

171 The session stays live after the PR is created. Paste CI failure output or reviewer comments into the chat and ask Claude to address them. To have Claude monitor the PR automatically, see [Auto-fix pull requests](/en/claude-code-on-the-web#auto-fix-pull-requests).

172 </Step>

173</Steps>

174 

175## Troubleshoot setup

176 

177### No repositories appear after connecting GitHub

178 

179The Claude GitHub App needs explicit access to each repository you want to use. On github.com, open **Settings → Applications → Claude → Configure** and verify your repo is listed under **Repository access**. Private repositories need the same authorization as public ones.

180 

181### The page only shows a GitHub login button

182 

183Cloud sessions require a connected GitHub account. Connect via the browser flow above, or run `/web-setup` from your terminal if you use the GitHub CLI. If you'd rather not connect GitHub at all, see [Remote Control](/en/remote-control) to run Claude Code on your own machine and monitor it from the web.

184 

185### "Not available for the selected organization"

186 

187Enterprise organizations may need an admin to enable Claude Code on the web. Contact your Anthropic account team.

188 

189### `/web-setup` returns "Unknown command"

190 

191`/web-setup` runs inside the Claude Code CLI, not your shell. Launch `claude` first, then type `/web-setup` at the prompt.

192 

193If you typed it inside Claude Code and still see the error, your CLI is older than v2.1.80 or you're authenticated with an API key or third-party provider instead of a claude.ai subscription. Run `claude update`, then `/login` to sign in with your claude.ai account.

194 

195### "Could not create a cloud environment" or "No cloud environment available" when using `--remote` or ultraplan

196 

197Remote-session features create a default cloud environment automatically if you don't have one. If you see "Could not create a cloud environment", automatic creation failed. {/* max-version: 2.1.100 */}If you see "No cloud environment available", your CLI predates automatic creation. In either case, run `/web-setup` in the Claude Code CLI to create one manually, or visit [claude.ai/code](https://claude.ai/code) and follow the **Create your environment** step above.

198 

199### Setup script failed

200 

201The setup script exited with a non-zero status, which blocks the session from starting. Common causes:

202 

203* A package install failed because the registry isn't in your [network access level](/en/claude-code-on-the-web#access-levels). `Trusted` covers most package managers; `None` blocks them all.

204* The script references a file or path that doesn't exist in a fresh clone.

205* A command that works locally needs a different invocation on Ubuntu.

206 

207To debug, add `set -x` at the top of the script to see which command failed. For non-critical commands, append `|| true` so they don't block session start.

208 

209### Session keeps running after closing the tab

210 

211This is by design. Closing the tab or navigating away doesn't stop the session. It continues running in the background until Claude finishes the current task, then idles. From the sidebar, you can [archive a session](/en/claude-code-on-the-web#archive-sessions) to hide it from your list, or [delete it](/en/claude-code-on-the-web#delete-sessions) to remove it permanently.

212 

213## Next steps

214 

215Now that you can submit and review tasks, these pages cover what comes next: starting cloud sessions from your terminal, scheduling recurring work, and giving Claude standing instructions.

216 

217* [Use Claude Code on the web](/en/claude-code-on-the-web): the full reference, including teleporting sessions to your terminal, setup scripts, environment variables, and network config

218* [Routines](/en/routines): automate work on a schedule, via API call, or in response to GitHub events

219* [CLAUDE.md](/en/memory): give Claude persistent instructions and context that load at the start of every session

220* Install the Claude mobile app for [iOS](https://apps.apple.com/us/app/claude-by-anthropic/id6473753684) or [Android](https://play.google.com/store/apps/details?id=com.anthropic.claude) to monitor sessions from your phone. From the Claude Code CLI, `/mobile` shows a QR code.

whats-new.md +49 −0 added

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# What's new

6 

7> A weekly digest of notable Claude Code features, with code snippets, demos, and context on why they matter.

8 

9The weekly dev digest highlights the features most likely to change how you work. Each entry includes runnable code, a short demo, and a link to the full docs. For every bug fix and minor improvement, see the [changelog](/en/changelog).

10 

11<Update label="Week 17" description="April 20–24, 2026" tags={["v2.1.114–v2.1.119"]}>

12 **`/ultrareview`** opens as a public research preview: a fleet of bug-hunting agents runs in the cloud and findings land back in your CLI or Desktop automatically.

13 

14 Also this week: **session recap** shows you what happened while a terminal was unfocused; **custom themes** let you build and ship color palettes from `/theme` or a plugin; and **Claude Code on the web** gets a redesign with a new sessions sidebar and drag-and-drop layout.

15 

16 [Read the Week 17 digest →](/en/whats-new/2026-w17)

17</Update>

18 

19<Update label="Week 16" description="April 13–17, 2026" tags={["v2.1.105–v2.1.113"]}>

20 **Claude Opus 4.7** lands as the new default on Max and Team Premium, with a new `xhigh` effort level that's the recommended setting for most coding work and an interactive `/effort` slider to dial it in.

21 

22 Also this week: **Routines** on Claude Code on the web fire templated cloud agents from a schedule, GitHub event, or API call; `/ultrareview` runs parallel multi-agent code review in the cloud; `/usage` shows what's driving your limits; and the CLI moves to native binaries.

23 

24 [Read the Week 16 digest →](/en/whats-new/2026-w16)

25</Update>

26 

27<Update label="Week 15" description="April 6–10, 2026" tags={["v2.1.92–v2.1.101"]}>

28 **Ultraplan** enters early preview: draft a plan in the cloud from your CLI, review and comment on it in a web editor, then run it remotely or pull it back local. The first run now auto-creates a cloud environment for you.

29 

30 Also this week: the **Monitor** tool streams background events into the conversation so Claude can tail logs and react live, `/loop` self-paces when you omit the interval, `/team-onboarding` packages your setup into a replayable guide, and `/autofix-pr` turns on PR auto-fix from your terminal.

31 

32 [Read the Week 15 digest →](/en/whats-new/2026-w15)

33</Update>

34 

35<Update label="Week 14" description="March 30 – April 3, 2026" tags={["v2.1.86–v2.1.91"]}>

36 **Computer use** comes to the CLI in research preview: Claude can open native apps, click through UI, and verify changes from your terminal. Best for closing the loop on things only a GUI can verify.

37 

38 Also this week: `/powerup` interactive lessons, flicker-free alt-screen rendering, a per-tool MCP result-size override up to 500K, and plugin executables on the Bash tool's `PATH`.

39 

40 [Read the Week 14 digest →](/en/whats-new/2026-w14)

41</Update>

42 

43<Update label="Week 13" description="March 23–27, 2026" tags={["v2.1.83–v2.1.85"]}>

44 **Auto mode** lands in research preview: a classifier handles your permission prompts so safe actions run without interruption and risky ones get blocked. The middle ground between approving everything and `--dangerously-skip-permissions`.

45 

46 Also this week: computer use in the Desktop app, PR auto-fix on Web, transcript search with `/`, a native PowerShell tool for Windows, and conditional `if` hooks.

47 

48 [Read the Week 13 digest →](/en/whats-new/2026-w13)

49</Update>

whats-new/2026-w13.md +164 −0 added

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# Week 13 · March 23–27, 2026

6 

7> Auto mode for hands-off permissions, computer use built in, PR auto-fix in the cloud, transcript search, and a PowerShell tool for Windows.

8 

9<div className="digest-meta">

10 <span>Releases <a href="/docs/en/changelog#2-1-83">v2.1.83 → v2.1.85</a></span>

11 <span>6 features · March 23–27</span>

12</div>

13 

14<div className="digest-feature">

15 <div className="digest-feature-header">

16 <span className="digest-feature-title">Auto mode</span>

17 <span className="digest-feature-pill">research preview</span>

18 </div>

19 

20 <p className="digest-feature-lede">Auto mode hands your permission prompts to a classifier. Safe edits and commands run without interrupting you; anything destructive or suspicious gets blocked and surfaced. It's the middle ground between approving every file write and running with <code>--dangerously-skip-permissions</code>.</p>

21 

22 <Frame>

23 <img src="https://mintcdn.com/claude-code/CfffsX01JHFnIKvD/images/whats-new/auto-mode.png?fit=max&auto=format&n=CfffsX01JHFnIKvD&q=85&s=367c9e9d4ba5bc57ec4b935154bf1fbb" alt="Claude Code prompt footer showing 'auto mode on (shift+tab to cycle)' indicator in yellow" width="2400" height="691" data-path="images/whats-new/auto-mode.png" />

24 </Frame>

25 

26 <p className="digest-feature-try">Cycle to auto with Shift+Tab, or set it as your default:</p>

27 

28 ```json .claude/settings.json {3} theme={null}

29 {

30 "permissions": {

31 "defaultMode": "auto"

32 }

33 }

34 ```

35 

36 <a className="digest-feature-link" href="/docs/en/permission-modes">Permission modes guide</a>

37</div>

38 

39<div className="digest-feature">

40 <div className="digest-feature-header">

41 <span className="digest-feature-title">Computer use</span>

42 <span className="digest-feature-pill">Desktop</span>

43 </div>

44 

45 <p className="digest-feature-lede">Claude can now control your actual desktop from the Claude Code Desktop app: open native apps, click through the iOS simulator, drive hardware control panels, and verify changes on screen. It's off by default and asks before each action. Best for the things nothing else can reach: apps without an API, proprietary tools, anything that only exists as a GUI.</p>

46 

47 <Frame>

48 <img src="https://mintcdn.com/claude-code/CfffsX01JHFnIKvD/images/whats-new/computer-use.png?fit=max&auto=format&n=CfffsX01JHFnIKvD&q=85&s=d631de2017edafff463505f8ddbc0f51" alt="Claude Desktop settings with the Computer use toggle enabled, showing the option to let Claude take screenshots and control your keyboard and mouse in apps you allow" width="2376" height="1210" data-path="images/whats-new/computer-use.png" />

49 </Frame>

50 

51 <p className="digest-feature-try">Enable it in Settings, grant the OS permissions, then ask Claude to verify a change end to end:</p>

52 

53 ```text Claude Code theme={null}

54 > Open the iOS simulator, tap through the onboarding flow, and screenshot each step

55 ```

56 

57 <a className="digest-feature-link" href="/docs/en/desktop#let-claude-use-your-computer">Computer use guide</a>

58</div>

59 

60<div className="digest-feature">

61 <div className="digest-feature-header">

62 <span className="digest-feature-title">PR auto-fix</span>

63 <span className="digest-feature-pill">Web</span>

64 </div>

65 

66 <p className="digest-feature-lede">Flip a switch when you open a PR and walk away. Claude watches CI, fixes the failures, handles the nits, and pushes until it's green. No more babysitting a PR through six rounds of lint errors.</p>

67 

68 <Frame>

69 <img src="https://mintcdn.com/claude-code/CfffsX01JHFnIKvD/images/whats-new/auto-fix.png?fit=max&auto=format&n=CfffsX01JHFnIKvD&q=85&s=c62b181c6c5d96929f0b43525f9f3584" alt="Claude Code web CI panel showing the Auto fix toggle enabled, with description 'Proactively fix CI failures and review comments'" width="960" height="444" data-path="images/whats-new/auto-fix.png" />

70 </Frame>

71 

72 <p className="digest-feature-try">After creating a PR on Claude Code web, toggle Auto fix in the CI panel.</p>

73 

74 <a className="digest-feature-link" href="/docs/en/claude-code-on-the-web#auto-fix-pull-requests">Auto-fix pull requests</a>

75</div>

76 

77<div className="digest-feature">

78 <div className="digest-feature-header">

79 <span className="digest-feature-title">Transcript search</span>

80 <span className="digest-feature-pill">v2.1.83</span>

81 </div>

82 

83 <p className="digest-feature-lede">Press <code>/</code> in transcript mode to search your conversation. <code>n</code> and <code>N</code> step through matches. Finally a way to find that one Bash command Claude ran 400 messages ago.</p>

84 

85 <p className="digest-feature-try">Open transcript mode and search:</p>

86 

87 ```text Claude Code theme={null}

88 Ctrl+O # open transcript

89 /migrate # search for "migrate"

90 n # next match

91 N # previous match

92 ```

93 

94 <a className="digest-feature-link" href="/docs/en/fullscreen#search-and-review-the-conversation">Fullscreen guide</a>

95</div>

96 

97<div className="digest-feature">

98 <div className="digest-feature-header">

99 <span className="digest-feature-title">PowerShell tool</span>

100 <span className="digest-feature-pill">preview</span>

101 <span className="digest-feature-pill">v2.1.84</span>

102 </div>

103 

104 <p className="digest-feature-lede">Windows gets a native PowerShell tool alongside Bash. Claude can run cmdlets, pipe objects, and work with Windows-native paths without translating everything through Git Bash.</p>

105 

106 <p className="digest-feature-try">Opt in from settings:</p>

107 

108 ```json .claude/settings.json {3} theme={null}

109 {

110 "env": {

111 "CLAUDE_CODE_USE_POWERSHELL_TOOL": "1"

112 }

113 }

114 ```

115 

116 <a className="digest-feature-link" href="/docs/en/tools-reference#powershell-tool">PowerShell tool docs</a>

117</div>

118 

119<div className="digest-feature">

120 <div className="digest-feature-header">

121 <span className="digest-feature-title">Conditional hooks</span>

122 <span className="digest-feature-pill">v2.1.85</span>

123 </div>

124 

125 <p className="digest-feature-lede">Hooks can now declare an <code>if</code> field using permission rule syntax. Your pre-commit check only spawns for <code>Bash(git commit \*)</code> instead of every bash call, cutting the process overhead on busy sessions.</p>

126 

127 <p className="digest-feature-try">Scope a hook to git commits only:</p>

128 

129 ```json .claude/settings.json {5} theme={null}

130 {

131 "hooks": {

132 "PreToolUse": [{

133 "hooks": [{

134 "if": "Bash(git commit *)",

135 "type": "command",

136 "command": ".claude/hooks/lint-staged.sh"

137 }]

138 }]

139 }

140 }

141 ```

142 

143 <a className="digest-feature-link" href="/docs/en/hooks">Hooks reference</a>

144</div>

145 

146<div className="digest-wins">

147 <p className="digest-wins-title">Other wins</p>

148 

149 <div className="digest-wins-grid">

150 <div>Plugin <code>userConfig</code> now public: prompt for settings at enable time, keychain-backed secrets</div>

151 <div>Pasted images insert <code>\[Image #N]</code> chips you can reference positionally</div>

152 <div><code>managed-settings.d/</code> drop-in directory for layered policy fragments</div>

153 <div><code>CwdChanged</code> and <code>FileChanged</code> hook events for direnv-style setups</div>

154 <div>Agents can declare <code>initialPrompt</code> in frontmatter to auto-submit a first turn</div>

155 <div><code>Ctrl+X Ctrl+E</code> opens your external editor, matching readline</div>

156 <div>Interrupting before any response restores your input automatically</div>

157 <div><code>/status</code> now works while Claude is responding</div>

158 <div>Deep links open in your preferred terminal, not first-detected</div>

159 <div>Idle-return nudge to <code>/clear</code> after 75+ minutes away</div>

160 <div>VS Code: rate limit banner, Esc-twice rewind picker</div>

161 </div>

162</div>

163 

164[Full changelog for v2.1.83–v2.1.85 →](/en/changelog#2-1-83)

whats-new/2026-w14.md +138 −0 added

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# Week 14 · March 30 – April 3, 2026

6 

7> Computer use in the CLI, interactive in-product lessons, flicker-free rendering, per-tool MCP result-size overrides, and plugin executables on PATH.

8 

9<div className="digest-meta">

10 <span>Releases <a href="/docs/en/changelog#2-1-86">v2.1.86 → v2.1.91</a></span>

11 <span>5 features · March 30 – April 3</span>

12</div>

13 

14<div className="digest-feature">

15 <div className="digest-feature-header">

16 <span className="digest-feature-title">Computer use in the CLI</span>

17 <span className="digest-feature-pill">research preview</span>

18 </div>

19 

20 <p className="digest-feature-lede">Last week computer use landed in the Desktop app. This week it's in the CLI: Claude can open native apps, click through UI, test its own changes, and fix what breaks, all from your terminal. Web apps already had verification loops; native iOS, macOS, and other GUI-only apps didn't. Now they do. Best for closing the loop on apps and tools where there's no API to call. Still early; expect rough edges.</p>

21 

22 <Frame>

23 <video autoPlay muted loop playsInline className="w-full" src="https://mintcdn.com/claude-code/CfffsX01JHFnIKvD/images/whats-new/cli-computer-use.mp4?fit=max&auto=format&n=CfffsX01JHFnIKvD&q=85&s=c17a337902308d7c9121013ded0494db" data-path="images/whats-new/cli-computer-use.mp4" />

24 </Frame>

25 

26 <p className="digest-feature-try">Run <code>/mcp</code>, find <code>computer-use</code>, and toggle it on. Then ask Claude to verify a change end to end:</p>

27 

28 ```text Claude Code theme={null}

29 > Open the iOS simulator, tap through onboarding, and screenshot each step

30 ```

31 

32 <a className="digest-feature-link" href="/docs/en/computer-use">Computer use guide</a>

33</div>

34 

35<div className="digest-feature">

36 <div className="digest-feature-header">

37 <span className="digest-feature-title">/powerup</span>

38 <span className="digest-feature-pill">v2.1.90</span>

39 </div>

40 

41 <p className="digest-feature-lede">Interactive lessons that teach Claude Code features through animated demos, right inside your terminal. Claude Code releases frequently, and features that would have changed how you work last month can slip by. Run <code>/powerup</code> once and you'll know what's there.</p>

42 

43 <Frame>

44 <video autoPlay muted loop playsInline className="w-full" src="https://mintcdn.com/claude-code/CfffsX01JHFnIKvD/images/whats-new/powerup.mp4?fit=max&auto=format&n=CfffsX01JHFnIKvD&q=85&s=fb88beddc0ecc8029da5ab029e4b28f1" data-path="images/whats-new/powerup.mp4" />

45 </Frame>

46 

47 <p className="digest-feature-try">Run it:</p>

48 

49 ```text Claude Code theme={null}

50 > /powerup

51 ```

52 

53 <a className="digest-feature-link" href="/docs/en/commands">Commands reference</a>

54</div>

55 

56<div className="digest-feature">

57 <div className="digest-feature-header">

58 <span className="digest-feature-title">Flicker-free rendering</span>

59 <span className="digest-feature-pill">v2.1.89</span>

60 </div>

61 

62 <p className="digest-feature-lede">Opt into a new alt-screen renderer with virtualized scrollback. The prompt input stays pinned to the bottom, mouse selection works across long conversations, and the flicker on redraw is gone. Unset <code>CLAUDE\_CODE\_NO\_FLICKER</code> to roll back.</p>

63 

64 <Frame>

65 <video autoPlay muted loop playsInline className="w-full" src="https://mintcdn.com/claude-code/CfffsX01JHFnIKvD/images/whats-new/flicker-free.mp4?fit=max&auto=format&n=CfffsX01JHFnIKvD&q=85&s=7719e35e52a3f9734b0cf69edac333ad" data-path="images/whats-new/flicker-free.mp4" />

66 </Frame>

67 

68 <p className="digest-feature-try">Set the env var and restart Claude Code:</p>

69 

70 ```bash theme={null}

71 export CLAUDE_CODE_NO_FLICKER=1

72 claude

73 ```

74 

75 <a className="digest-feature-link" href="/docs/en/fullscreen">Fullscreen rendering</a>

76</div>

77 

78<div className="digest-feature">

79 <div className="digest-feature-header">

80 <span className="digest-feature-title">MCP result-size override</span>

81 <span className="digest-feature-pill">v2.1.91</span>

82 </div>

83 

84 <p className="digest-feature-lede">MCP server authors can now raise the truncation cap on a specific tool by setting <code>anthropic/maxResultSizeChars</code> in the tool's <code>tools/list</code> entry, up to a hard ceiling of 500K characters. The cap used to be global, so tools that occasionally returned inherently large payloads like database schemas or full file trees hit the default limit and got persisted to disk with a file reference. Per-tool overrides keep those results inline when the tool really needs them.</p>

85 

86 <p className="digest-feature-try">Annotate the tool in your server's <code>tools/list</code> response:</p>

87 

88 ```json highlight={5} theme={null}

89 {

90 "name": "get_schema",

91 "description": "Returns the full database schema",

92 "_meta": {

93 "anthropic/maxResultSizeChars": 500000

94 }

95 }

96 ```

97 

98 <a className="digest-feature-link" href="/docs/en/mcp#raise-the-limit-for-a-specific-tool">MCP reference</a>

99</div>

100 

101<div className="digest-feature">

102 <div className="digest-feature-header">

103 <span className="digest-feature-title">Plugin executables on PATH</span>

104 <span className="digest-feature-pill">v2.1.91</span>

105 </div>

106 

107 <p className="digest-feature-lede">Place an executable in a <code>bin/</code> directory at your plugin root and Claude Code adds that directory to the Bash tool's <code>PATH</code> while the plugin is enabled. Claude can then invoke the binary as a bare command from any Bash tool call, with no absolute path or wrapper script needed. Handy for packaging CLI helpers next to the commands, agents, and hooks that call them.</p>

108 

109 <p className="digest-feature-try">Add a <code>bin/</code> directory at the plugin root:</p>

110 

111 ```text highlight={4, 5} theme={null}

112 my-plugin/

113 ├── .claude-plugin/

114 │ └── plugin.json

115 └── bin/

116 └── my-tool

117 ```

118 

119 <a className="digest-feature-link" href="/docs/en/plugins-reference#file-locations-reference">Plugins reference</a>

120</div>

121 

122<div className="digest-wins">

123 <p className="digest-wins-title">Other wins</p>

124 

125 <div className="digest-wins-grid">

126 <div>Auto mode follow-ups: new <code>PermissionDenied</code> hook fires on classifier denials (return <code>retry: true</code> to let Claude try a different approach), and <code>/permissions</code> → Recent lets you retry manually with <code>r</code></div>

127 <div>New <code>defer</code> value for <code>permissionDecision</code> in <code>PreToolUse</code> hooks: <code>-p</code> sessions pause at a tool call and exit with a <code>deferred\_tool\_use</code> payload so an SDK app or custom UI can surface it, then resume with <code>--resume</code></div>

128 <div><code>/buddy</code>: hatch a small creature that watches you code (April 1st)</div>

129 <div><code>disableSkillShellExecution</code> setting blocks inline shell from skills, slash commands, and plugin commands</div>

130 <div>Edit tool now works on files viewed via <code>cat</code> or <code>sed -n</code> without a separate Read</div>

131 <div>Hook output over 50K saved to disk with a path + preview instead of injected into context</div>

132 <div>Thinking summaries off by default in interactive sessions (<code>showThinkingSummaries: true</code> to restore)</div>

133 <div>Voice mode: push-to-talk modifier combos, Windows WebSocket, macOS Apple Silicon mic permission</div>

134 <div><code>claude-cli://</code> deep links accept multi-line prompts (encoded <code>%0A</code>)</div>

135 </div>

136</div>

137 

138[Full changelog for v2.1.86–v2.1.91 →](/en/changelog#2-1-86)

whats-new/2026-w15.md +119 −0 added

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# Week 15 · April 6–10, 2026

6 

7> Ultraplan cloud planning, the Monitor tool with self-pacing /loop, /team-onboarding for packaging your setup, and /autofix-pr from your terminal.

8 

9<div className="digest-meta">

10 <span>Releases <a href="/docs/en/changelog#2-1-92">v2.1.92 → v2.1.101</a></span>

11 <span>4 features · April 6–10</span>

12</div>

13 

14<div className="digest-feature">

15 <div className="digest-feature-header">

16 <span className="digest-feature-title">Ultraplan</span>

17 <span className="digest-feature-pill">research preview</span>

18 </div>

19 

20 <p className="digest-feature-lede">Kick off plan mode in the cloud from your terminal, then review the result in your browser. Claude drafts the plan in a Claude Code on the web session while your terminal stays free; when it's ready you comment on individual sections, ask for revisions, and choose to execute remotely or send it back to your CLI. As of v2.1.101 the first run auto-creates a default cloud environment, so there's no web setup step before you can try it.</p>

21 

22 <Frame>

23 <video autoPlay muted loop playsInline className="w-full" src="https://mintcdn.com/claude-code/aFXPQxiBOW99MHS3/images/whats-new/ultraplan.mp4?fit=max&auto=format&n=aFXPQxiBOW99MHS3&q=85&s=e8f2f23730c6a5c289dbf3e7b13eadf6" data-path="images/whats-new/ultraplan.mp4" />

24 </Frame>

25 

26 <p className="digest-feature-try">Run the command, or just include the keyword in any prompt:</p>

27 

28 ```text Claude Code theme={null}

29 > /ultraplan migrate the auth service from sessions to JWTs

30 ```

31 

32 <a className="digest-feature-link" href="/docs/en/ultraplan">Ultraplan guide</a>

33</div>

34 

35<div className="digest-feature">

36 <div className="digest-feature-header">

37 <span className="digest-feature-title">Monitor tool</span>

38 <span className="digest-feature-pill">v2.1.98</span>

39 </div>

40 

41 <p className="digest-feature-lede">A new built-in tool that spawns a background watcher and streams its events into the conversation: each event lands as a new transcript message that Claude reacts to immediately. Tail a training run, babysit a PR's CI, or auto-fix a dev server crash the moment it happens, all without a Bash sleep loop holding the turn open.</p>

42 

43 <Frame>

44 <video autoPlay muted loop playsInline className="w-full" src="https://mintcdn.com/claude-code/aFXPQxiBOW99MHS3/images/whats-new/monitor-tool.mp4?fit=max&auto=format&n=aFXPQxiBOW99MHS3&q=85&s=f4156c15a0999de5c5157f54a3117c89" data-path="images/whats-new/monitor-tool.mp4" />

45 </Frame>

46 

47 <p className="digest-feature-try">Ask Claude to watch something while you keep working:</p>

48 

49 ```text Claude Code theme={null}

50 > Tail server.log in the background and tell me the moment a 5xx shows up

51 ```

52 

53 <p className="digest-feature-try">This pairs with <code>/loop</code>, which now self-paces: omit the interval and Claude schedules the next tick based on the task, or reaches for the Monitor tool to skip polling altogether.</p>

54 

55 ```text Claude Code theme={null}

56 > /loop check CI on my PR

57 ```

58 

59 <a className="digest-feature-link" href="/docs/en/tools-reference#monitor-tool">Monitor tool reference</a>

60</div>

61 

62<div className="digest-feature">

63 <div className="digest-feature-header">

64 <span className="digest-feature-title">/autofix-pr</span>

65 <span className="digest-feature-pill">CLI</span>

66 </div>

67 

68 <p className="digest-feature-lede">PR auto-fix landed on the web in Week 13. Now you can turn it on without leaving your terminal: <code>/autofix-pr</code> infers the open PR for your current branch and enables auto-fix for it on Claude Code on the web in one step. Push your branch, run the command, walk away; Claude watches CI and review comments and pushes fixes until it's green.</p>

69 

70 <Frame>

71 <video autoPlay muted loop playsInline className="w-full" src="https://mintcdn.com/claude-code/aFXPQxiBOW99MHS3/images/whats-new/autofix-pr.mp4?fit=max&auto=format&n=aFXPQxiBOW99MHS3&q=85&s=95f191eb4711130a128aec3f6b720527" data-path="images/whats-new/autofix-pr.mp4" />

72 </Frame>

73 

74 <p className="digest-feature-try">Run it from the PR's branch:</p>

75 

76 ```text Claude Code theme={null}

77 > /autofix-pr

78 ```

79 

80 <a className="digest-feature-link" href="/docs/en/claude-code-on-the-web#auto-fix-pull-requests">Auto-fix pull requests</a>

81</div>

82 

83<div className="digest-feature">

84 <div className="digest-feature-header">

85 <span className="digest-feature-title">/team-onboarding</span>

86 <span className="digest-feature-pill">v2.1.101</span>

87 </div>

88 

89 <p className="digest-feature-lede">Generates a teammate ramp-up guide from your local Claude Code usage. Run it in a project you know well and hand the output to a new teammate so they can replay your setup instead of starting from defaults.</p>

90 

91 <p className="digest-feature-try">Run it from a project you've spent real time in:</p>

92 

93 ```text Claude Code theme={null}

94 > /team-onboarding

95 ```

96 

97 <a className="digest-feature-link" href="/docs/en/commands">Commands reference</a>

98</div>

99 

100<div className="digest-wins">

101 <p className="digest-wins-title">Other wins</p>

102 

103 <div className="digest-wins-grid">

104 <div>Focus view: press <code>Ctrl+O</code> in flicker-free mode to collapse the view to your last prompt, a one-line tool summary with diffstats, and Claude's final response</div>

105 <div>Guided <a href="/docs/en/amazon-bedrock">Bedrock</a> and <a href="/docs/en/google-vertex-ai">Vertex AI</a> setup wizards on the login screen: pick "3rd-party platform" for step-by-step auth, region, credential check, and model pinning</div>

106 <div><code>/agents</code> gets a tabbed layout: a Running tab shows live subagents with a <code>● N running</code> count, plus Run agent and View running instance actions in the Library tab</div>

107 <div>Default effort level is now <code>high</code> for API-key, Bedrock, Vertex, Foundry, Team, and Enterprise users (control with <code>/effort</code>)</div>

108 <div><code>/cost</code> shows a per-model and cache-hit breakdown for subscription users</div>

109 <div><code>/release-notes</code> is now an interactive version picker</div>

110 <div>Status line: new <code>refreshInterval</code> setting re-runs the command every N seconds, and <code>workspace.git\_worktree</code> in the JSON input</div>

111 <div><code>CLAUDE\_CODE\_PERFORCE\_MODE</code>: Edit/Write fail on read-only files with a <code>p4 edit</code> hint instead of silently overwriting</div>

112 <div>OS CA certificate store is now trusted by default, so enterprise TLS proxies work without extra setup (<code>CLAUDE\_CODE\_CERT\_STORE=bundled</code> to opt out)</div>

113 <div>Amazon Bedrock powered by Mantle: set <code>CLAUDE\_CODE\_USE\_MANTLE=1</code></div>

114 <div>Hardened Bash tool permissions: backslash-escaped flags, env-var prefixes, <code>/dev/tcp</code> redirects, and compound commands now prompt correctly</div>

115 <div><code>UserPromptSubmit</code> hooks can set the session title via <code>hookSpecificOutput.sessionTitle</code></div>

116 </div>

117</div>

118 

119[Full changelog for v2.1.92–v2.1.101 →](/en/changelog#2-1-92)

whats-new/2026-w16.md +135 −0 added

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# Week 16 · April 13–17, 2026

6 

7> Claude Opus 4.7 with the new xhigh effort level, Routines on Claude Code on the web, /ultrareview cloud code review, a /usage breakdown that shows what's driving your limits, and native binaries replacing the bundled JavaScript.

8 

9<div className="digest-meta">

10 <span>Releases <a href="/docs/en/changelog#2-1-105">v2.1.105 → v2.1.113</a></span>

11 <span>5 features · April 13–17</span>

12</div>

13 

14<div className="digest-feature">

15 <div className="digest-feature-header">

16 <span className="digest-feature-title">Claude Opus 4.7</span>

17 <span className="digest-feature-pill">new model</span>

18 </div>

19 

20 <p className="digest-feature-lede">Anthropic's strongest coding model yet is now the default on Max and Team Premium, and available everywhere else from <code>/model</code>. It adds a new <code>xhigh</code> effort level that sits between <code>high</code> and <code>max</code>: best results for most coding and agentic tasks, applied as the default the first time you switch to 4.7. <code>/effort</code> now opens an interactive arrow-key slider when you call it without arguments, so you can dial intelligence against speed without remembering the level names.</p>

21 

22 <p className="digest-feature-try">Switch model and effort in one go:</p>

23 

24 ```text Claude Code theme={null}

25 > /model opus

26 > /effort xhigh

27 ```

28 

29 <a className="digest-feature-link" href="/docs/en/model-config#adjust-effort-level">Model config: effort levels</a>

30</div>

31 

32<div className="digest-feature">

33 <div className="digest-feature-header">

34 <span className="digest-feature-title">Routines</span>

35 <span className="digest-feature-pill">web</span>

36 </div>

37 

38 <p className="digest-feature-lede">Templated cloud agents that fire on a schedule, a GitHub event, or an API call. Define a routine once on Claude Code on the web with a prompt, the repos it can touch, and the connectors it needs, then let PR-opened, release-published, or your own webhook trigger it without your machine running. The trigger picker now covers GitHub events with optional filters and gives every routine a tokened <code>/fire</code> endpoint for external systems.</p>

39 

40 <Frame>

41 <img className="w-full" src="https://mintcdn.com/claude-code/FTi4SBJ9YRs7d-5X/images/whats-new/routines.png?fit=max&auto=format&n=FTi4SBJ9YRs7d-5X&q=85&s=2ba818ea9280c549511cb48b9b4d1dc5" alt="Creating a routine on Claude Code on the web with schedule, GitHub event, and API triggers" width="1440" height="810" data-path="images/whats-new/routines.png" />

42 </Frame>

43 

44 <p className="digest-feature-try">Create one from the web UI, or scaffold from your terminal:</p>

45 

46 ```text Claude Code theme={null}

47 > /schedule daily PR review at 9am

48 ```

49 

50 <a className="digest-feature-link" href="/docs/en/routines">Routines guide</a>

51</div>

52 

53<div className="digest-feature">

54 <div className="digest-feature-header">

55 <span className="digest-feature-title">/usage breakdown</span>

56 <span className="digest-feature-pill">CLI</span>

57 </div>

58 

59 <p className="digest-feature-lede">More visibility into where your Claude Code usage goes. <code>/usage</code> now shows what's driving your limits: parallel sessions, subagents, cache misses, and long context, each with a percentage of your last 24 hours and a tip to optimize it. Press <code>d</code> or <code>w</code> to switch between day and week views.</p>

60 

61 <Frame>

62 <img className="w-full" src="https://mintcdn.com/claude-code/FTi4SBJ9YRs7d-5X/images/whats-new/usage.png?fit=max&auto=format&n=FTi4SBJ9YRs7d-5X&q=85&s=792a4b43cbef4e2931974831f076bca6" alt="The /usage command showing a breakdown of what's contributing to limits usage" width="1204" height="1182" data-path="images/whats-new/usage.png" />

63 </Frame>

64 

65 <p className="digest-feature-try">Run it any time:</p>

66 

67 ```text Claude Code theme={null}

68 > /usage

69 ```

70 

71 <a className="digest-feature-link" href="/docs/en/commands">Commands reference</a>

72</div>

73 

74<div className="digest-feature">

75 <div className="digest-feature-header">

76 <span className="digest-feature-title">/ultrareview</span>

77 <span className="digest-feature-pill">v2.1.111</span>

78 </div>

79 

80 <p className="digest-feature-lede">Comprehensive code review in the cloud. Ultrareview fans your branch out across parallel reviewers on Claude Code on the web, runs an adversarial critique pass over each finding, and returns a verified findings report while your terminal stays free. Call it with no arguments to review your current branch, or pass a PR number to fetch and review that PR. The launch dialog now shows a diffstat so you know what's going up before you confirm.</p>

81 

82 <p className="digest-feature-try">Review the branch you're on:</p>

83 

84 ```text Claude Code theme={null}

85 > /ultrareview

86 ```

87 

88 <p className="digest-feature-try">Or point it at a PR:</p>

89 

90 ```text Claude Code theme={null}

91 > /ultrareview 1234

92 ```

93 

94 <a className="digest-feature-link" href="/docs/en/ultrareview">Ultrareview guide</a>

95</div>

96 

97<div className="digest-feature">

98 <div className="digest-feature-header">

99 <span className="digest-feature-title">Native binaries</span>

100 <span className="digest-feature-pill">v2.1.113</span>

101 </div>

102 

103 <p className="digest-feature-lede">The <code>claude</code> CLI now spawns a native per-platform binary instead of bundled JavaScript, so the installed <code>claude</code> command no longer invokes Node. The npm package pulls the right binary in through an optional dependency such as <code>@anthropic-ai/claude-code-darwin-arm64</code>, so your install command doesn't change. The standalone installer already shipped this binary; npm now matches it.</p>

104 

105 <p className="digest-feature-try">Upgrade and check what you're running:</p>

106 

107 ```bash theme={null}

108 claude update

109 claude --version

110 ```

111 

112 <a className="digest-feature-link" href="/docs/en/setup">Setup guide</a>

113</div>

114 

115<div className="digest-wins">

116 <p className="digest-wins-title">Other wins</p>

117 

118 <div className="digest-wins-grid">

119 <div><a href="/docs/en/permission-modes#eliminate-prompts-with-auto-mode">Auto mode</a> is now available for Max subscribers on Opus 4.7, and the <code>--enable-auto-mode</code> flag is no longer required</div>

120 <div><a href="/docs/en/interactive-mode#session-recap">Session recap</a> shows a one-line summary of what happened while you were away; run <code>/recap</code> on demand or turn it off from <code>/config</code></div>

121 <div>New <code>/tui</code> command and <code>tui</code> setting switch between classic and flicker-free rendering mid-conversation; focus view moved from <code>Ctrl+O</code> to its own <code>/focus</code> command</div>

122 <div>Push notification tool: with <a href="/docs/en/remote-control">Remote Control</a> connected and "Push when Claude decides" enabled, Claude can ping your phone when it needs you</div>

123 <div>Plugins can ship background watchers via a top-level <code>monitors</code> manifest key that auto-arms at session start or on skill invoke</div>

124 <div>"Auto (match terminal)" option in <code>/theme</code> follows your terminal's dark/light mode</div>

125 <div><code>/fewer-permission-prompts</code> scans your transcripts for common read-only Bash and MCP calls and proposes an allowlist for <code>.claude/settings.json</code></div>

126 <div>Claude can now discover and run built-in commands like <code>/init</code>, <code>/review</code>, and <code>/security-review</code> via the Skill tool</div>

127 <div><code>PreCompact</code> hooks can block compaction by exiting with code 2 or returning <code>{"{"}"decision":"block"{"}"}</code></div>

128 <div><code>ENABLE\_PROMPT\_CACHING\_1H</code> opts API key, Bedrock, Vertex, and Foundry users into 1-hour prompt cache TTL</div>

129 <div><code>sandbox.network.deniedDomains</code> setting carves specific domains out of a broader <code>allowedDomains</code> wildcard</div>

130 <div><code>/undo</code> is now an alias for <code>/rewind</code>, and <code>/proactive</code> is an alias for <code>/loop</code></div>

131 <div>Hardened Bash permissions: deny rules now match through <code>env</code>/<code>sudo</code>/<code>watch</code> wrappers, and <code>Bash(find:\*)</code> allow rules no longer auto-approve <code>-exec</code> or <code>-delete</code></div>

132 </div>

133</div>

134 

135[Full changelog for v2.1.105–v2.1.113 →](/en/changelog#2-1-105)

whats-new/2026-w17.md +113 −0 added

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# Week 17 · April 20–24, 2026

6 

7> /ultrareview opens as a research preview, automatic session recaps when you return to a terminal, custom color themes you can build and ship in plugins, and a redesigned Claude Code on the web.

8 

9<div className="digest-meta">

10 <span>Releases <a href="/docs/en/changelog#2-1-114">v2.1.114 → v2.1.119</a></span>

11 <span>4 features · April 20–24</span>

12</div>

13 

14<div className="digest-feature">

15 <div className="digest-feature-header">

16 <span className="digest-feature-title">/ultrareview</span>

17 <span className="digest-feature-pill">research preview</span>

18 </div>

19 

20 <p className="digest-feature-lede">Now in public research preview. Ultrareview runs a fleet of bug-hunting agents in the cloud against your branch or a PR, and findings land back in the CLI or Desktop automatically. Run it before merging critical changes such as auth or data migrations.</p>

21 

22 <Frame>

23 <video autoPlay muted loop playsInline className="w-full" src="https://mintcdn.com/claude-code/FTi4SBJ9YRs7d-5X/images/whats-new/ultrareview.mp4?fit=max&auto=format&n=FTi4SBJ9YRs7d-5X&q=85&s=0fb1271365d38f414ad155aeb8edb08e" data-path="images/whats-new/ultrareview.mp4" />

24 </Frame>

25 

26 <p className="digest-feature-try">Review the branch you're on:</p>

27 

28 ```text Claude Code theme={null}

29 > /ultrareview

30 ```

31 

32 <p className="digest-feature-try">Or point it at a PR:</p>

33 

34 ```text Claude Code theme={null}

35 > /ultrareview 1234

36 ```

37 

38 <a className="digest-feature-link" href="/docs/en/ultrareview">Ultrareview guide</a>

39</div>

40 

41<div className="digest-feature">

42 <div className="digest-feature-header">

43 <span className="digest-feature-title">Session recap</span>

44 <span className="digest-feature-pill">CLI</span>

45 </div>

46 

47 <p className="digest-feature-lede">Switch focus away from a session and come back to a one-line recap of what happened while you were gone. Helpful for staying in flow while running several Claude sessions at once.</p>

48 

49 <Frame>

50 <video autoPlay muted loop playsInline className="w-full" src="https://mintcdn.com/claude-code/FTi4SBJ9YRs7d-5X/images/whats-new/session-recap.mp4?fit=max&auto=format&n=FTi4SBJ9YRs7d-5X&q=85&s=0a8db1470bd0161a47efeb2f322af76f" data-path="images/whats-new/session-recap.mp4" />

51 </Frame>

52 

53 <p className="digest-feature-try">Generate a recap on demand, or turn the automatic one off from <code>/config</code>:</p>

54 

55 ```text Claude Code theme={null}

56 > /recap

57 ```

58 

59 <a className="digest-feature-link" href="/docs/en/interactive-mode#session-recap">Interactive mode: session recap</a>

60</div>

61 

62<div className="digest-feature">

63 <div className="digest-feature-header">

64 <span className="digest-feature-title">Custom themes</span>

65 <span className="digest-feature-pill">v2.1.118</span>

66 </div>

67 

68 <p className="digest-feature-lede">Build and switch between named color themes from <code>/theme</code>, or hand-edit JSON files in <code>\~/.claude/themes/</code>. Each theme picks a base preset and overrides only the tokens you care about. Plugins can ship themes too.</p>

69 

70 <p className="digest-feature-try">Open the theme picker and create a new one:</p>

71 

72 ```text Claude Code theme={null}

73 > /theme

74 ```

75 

76 <a className="digest-feature-link" href="/docs/en/terminal-config#create-a-custom-theme">Terminal config: create a custom theme</a>

77</div>

78 

79<div className="digest-feature">

80 <div className="digest-feature-header">

81 <span className="digest-feature-title">Claude Code on the web</span>

82 <span className="digest-feature-pill">web</span>

83 </div>

84 

85 <p className="digest-feature-lede">A new look for <a href="https://claude.ai/code">claude.ai/code</a> that matches the redesigned desktop app: sessions sidebar, drag-and-drop layout, and a refreshed routines view. Key parts were rebuilt for quicker responses and a more reliable experience.</p>

86 

87 <Frame>

88 <img className="w-full" src="https://mintcdn.com/claude-code/FTi4SBJ9YRs7d-5X/images/whats-new/web-redesign.jpeg?fit=max&auto=format&n=FTi4SBJ9YRs7d-5X&q=85&s=a2aca1b49e295b7337f5779038db8e2c" alt="Claude Code on the web redesign overview: new UI, speed and reliability, work across web, mobile, and CLI" width="1602" height="1610" data-path="images/whats-new/web-redesign.jpeg" />

89 </Frame>

90 

91 <a className="digest-feature-link" href="/docs/en/claude-code-on-the-web">Claude Code on the web</a>

92</div>

93 

94<div className="digest-wins">

95 <p className="digest-wins-title">Other wins</p>

96 

97 <div className="digest-wins-grid">

98 <div><a href="/docs/en/interactive-mode#vim-editor-mode">Vim visual mode</a>: press <code>v</code> for character selection or <code>V</code> for line selection in the prompt input, with operators and visual feedback</div>

99 <div>Hooks can now call MCP tools directly via <a href="/docs/en/hooks#mcp-tool-hook-fields"><code>type: "mcp\_tool"</code></a>, so a hook can hit an already-connected server without spawning a process</div>

100 <div><code>/cost</code> and <code>/stats</code> are merged into <a href="/docs/en/commands"><code>/usage</code></a>; the old names still work as typing shortcuts that open the relevant tab</div>

101 <div><code>/config</code> changes (theme, editor mode, verbose, and similar) now persist to <code>\~/.claude/settings.json</code> and follow the same project/local/policy precedence as other <a href="/docs/en/settings">settings</a></div>

102 <div><a href="/docs/en/sub-agents#fork-the-current-conversation">Forked subagents</a> can be enabled on external builds with <code>CLAUDE\_CODE\_FORK\_SUBAGENT=1</code>: a fork inherits your full conversation context instead of starting fresh</div>

103 <div>Default <a href="/docs/en/model-config#adjust-effort-level">effort level</a> for Pro and Max subscribers on Opus 4.6 and Sonnet 4.6 is now <code>high</code> (was <code>medium</code>)</div>

104 <div>Native macOS and Linux builds replace the <code>Glob</code> and <code>Grep</code> tools with embedded <code>bfs</code> and <code>ugrep</code> available through Bash, for faster searches without a separate tool round-trip</div>

105 <div><code>--from-pr</code> now accepts GitLab merge request, Bitbucket pull request, and GitHub Enterprise PR URLs in addition to github.com</div>

106 <div>Auto mode: include <code>"\$defaults"</code> in <a href="/docs/en/auto-mode-config"><code>autoMode.allow</code>, <code>soft\_deny</code>, or <code>environment</code></a> to add custom rules alongside the built-in list instead of replacing it</div>

107 <div>New <a href="/docs/en/plugin-dependencies#tag-plugin-releases-for-version-resolution"><code>claude plugin tag</code></a> command creates release git tags for plugins with version validation</div>

108 <div>Opus 4.7 sessions now compute against the model's native 1M context window, fixing inflated <code>/context</code> percentages and premature autocompaction</div>

109 <div><code>/resume</code> on large sessions is up to 67% faster and now offers to summarize stale, large sessions before re-reading them</div>

110 </div>

111</div>

112 

113[Full changelog for v2.1.114–v2.1.119 →](/en/changelog#2-1-114)

zero-data-retention.md +66 −0 added

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# Zero data retention

6 

7> Learn about Zero Data Retention (ZDR) for Claude Code on Claude for Enterprise, including scope, disabled features, and how to request enablement.

8 

9Zero Data Retention (ZDR) is available for Claude Code when used through Claude for Enterprise. When ZDR is enabled, prompts and model responses generated during Claude Code sessions are processed in real time and not stored by Anthropic after the response is returned, except where needed to comply with law or combat misuse.

10 

11ZDR on Claude for Enterprise gives enterprise customers the ability to use Claude Code with zero data retention and access administrative capabilities:

12 

13* Cost controls per user

14* [Analytics](/en/analytics) dashboard

15* [Server-managed settings](/en/server-managed-settings)

16* Audit logs

17 

18ZDR for Claude Code on Claude for Enterprise applies only to Anthropic's direct platform. For Claude deployments on AWS Bedrock, Google Vertex AI, or Microsoft Foundry, refer to those platforms' data retention policies.

19 

20## ZDR scope

21 

22ZDR covers Claude Code inference on Claude for Enterprise.

23 

24<Warning>

25 ZDR is enabled on a per-organization basis. Each new organization requires ZDR to be enabled separately by your Anthropic account team. ZDR does not automatically apply to new organizations created under the same account. Contact your account team to enable ZDR for any new organizations.

26</Warning>

27 

28### What ZDR covers

29 

30ZDR covers model inference calls made through Claude Code on Claude for Enterprise. When you use Claude Code in your terminal, the prompts you send and the responses Claude generates are not retained by Anthropic. This applies regardless of which Claude model is used.

31 

32### What ZDR does not cover

33 

34ZDR does not extend to the following, even for organizations with ZDR enabled. These features follow [standard data retention policies](/en/data-usage#data-retention):

35 

36| Feature | Details |

37| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

38| Chat on claude.ai | Chat conversations through the Claude for Enterprise web interface are not covered by ZDR. |

39| Cowork | Cowork sessions are not covered by ZDR. |

40| Claude Code Analytics | Does not store prompts or model responses, but collects productivity metadata such as account emails and usage statistics. Contribution metrics are not available for ZDR organizations; the [analytics dashboard](/en/analytics) shows usage metrics only. |

41| User and seat management | Administrative data such as account emails and seat assignments is retained under standard policies. |

42| Third-party integrations | Data processed by third-party tools, MCP servers, or other external integrations is not covered by ZDR. Review those services' data handling practices independently. |

43 

44## Features disabled under ZDR

45 

46When ZDR is enabled for a Claude Code organization on Claude for Enterprise, certain features that require storing prompts or completions are automatically disabled at the backend level:

47 

48| Feature | Reason |

49| ------------------------------------------------------------------- | ----------------------------------------------------------------------- |

50| [Claude Code on the Web](/en/claude-code-on-the-web) | Requires server-side storage of conversation history. |

51| [Remote sessions](/en/desktop#remote-sessions) from the Desktop app | Requires persistent session data that includes prompts and completions. |

52| Feedback submission (`/feedback`) | Submitting feedback sends conversation data to Anthropic. |

53 

54These features are blocked in the backend regardless of client-side display. If you see a disabled feature in the Claude Code terminal during startup, attempting to use it returns an error indicating the organization's policies do not allow that action.

55 

56Future features may also be disabled if they require storing prompts or completions.

57 

58## Data retention for policy violations

59 

60Even with ZDR enabled, Anthropic may retain data where required by law or to address Usage Policy violations. If a session is flagged for a policy violation, Anthropic may retain the associated inputs and outputs for up to 2 years, consistent with Anthropic's standard ZDR policy.

61 

62## Request ZDR

63 

64To request ZDR for Claude Code on Claude for Enterprise, [contact sales](https://www.anthropic.com/contact-sales?utm_source=claude_code\&utm_medium=docs\&utm_content=zero_data_retention_request) or your Anthropic account team. Your account team will submit the request internally, and Anthropic will review and enable ZDR on your organization after confirming eligibility. All enablement actions are audit-logged.

65 

66If you are currently using ZDR for Claude Code via pay-as-you-go API keys, you can transition to Claude for Enterprise to gain access to administrative features while maintaining ZDR for Claude Code. Contact your account team to coordinate the migration.