All settings changedsettings-reference
Nearest release: v2.1.305, published an hour after upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 20 Oct 2026 18:25 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 20 Oct 2026 18:37 UTC.
Upstream edited
Recorded here
Lines+36added
Lines−659removed
From line
2
where the diff opens
First seen
21 Aug 2026
this site's first read of the page
Recorded edits143to this page, all time
The whole hunk
from line 2, old and new numbered
/
This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.
The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.
from line 2
22
33> Complete reference for every Claude Code settings.json key: where each one goes, its type and default, and a paste-ready example, with an index of every key.
44
5export const BackToIndex = ({href = '#all-settings', label = 'Back to index'}) => {
6 const [show, setShow] = useState(false);
7 useEffect(() => {
8 const onScroll = () => setShow(window.scrollY > window.innerHeight);
9 onScroll();
10 window.addEventListener('scroll', onScroll, {
11 passive: true
12 });
13 return () => window.removeEventListener('scroll', onScroll);
14 }, []);
15 return <div className="not-prose">
16 <style>{`
17 .bti-btn {
18 position: fixed; right: 20px; bottom: 20px; z-index: 40;
19 display: inline-flex; align-items: center; gap: 6px;
20 padding: 8px 12px; border-radius: 999px;
21 font-size: 13px; font-weight: 500; line-height: 1; text-decoration: none;
22 color: #1f1f1f; background: #ffffff; border: 1px solid #d9d9d9;
23 box-shadow: 0 2px 8px rgba(0,0,0,0.12);
24 opacity: 0; pointer-events: none; transform: translateY(6px);
25 transition: opacity 160ms ease, transform 160ms ease;
26 }
27 .bti-btn.bti-show { opacity: 1; pointer-events: auto; transform: translateY(0); }
28 .bti-btn:hover { border-color: #b3b3b3; }
29 .dark .bti-btn { color: #ececec; background: #1e1e1e; border-color: #3a3a3a; box-shadow: 0 2px 8px rgba(0,0,0,0.5); }
30 .dark .bti-btn:hover { border-color: #5a5a5a; }
31 @media (max-width: 1279px) { .bti-btn { bottom: 112px; } }
32 @media print { .bti-btn { display: none; } }
33 `}</style>
34 <a className={'bti-btn' + (show ? ' bti-show' : '')} href={href} aria-hidden={!show} tabIndex={show ? 0 : -1}>
35 <svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M8 13V3M3.5 7.5 8 3l4.5 4.5" /></svg>
36 {label}
37 </a>
38 </div>;
39};
40
41export const ReferenceFilter = ({placeholder, noun, facets, facetOrder, columnHelp, children}) => {
42 const useLive = init => {
43 const [v, setV] = useState(init);
44 const ref = useRef(init);
45 return [v, ref, x => {
46 ref.current = x;
47 setV(x);
48 }];
49 };
50 const cap = s => s.charAt(0).toUpperCase() + s.slice(1);
51 const plural = s => s.endsWith('y') ? s.slice(0, -1) + 'ies' : s + 's';
52 const facetNames = facets || ['category', 'topic', 'scope', 'where'];
53 const orderOf = {};
54 Object.keys(facetOrder || ({})).forEach(k => {
55 orderOf[k] = facetOrder[k].map(x => String(x).toLowerCase());
56 });
57 const rankIn = (col, v) => {
58 const list = orderOf[col];
59 if (!list) return -1;
60 const i = list.indexOf(String(v).toLowerCase());
61 return i < 0 ? list.length : i;
62 };
63 const cmpValues = col => (a, b) => {
64 const ra = rankIn(col, a);
65 const rb = rankIn(col, b);
66 if (ra !== rb) return ra - rb;
67 return a < b ? -1 : a > b ? 1 : 0;
68 };
69 const help = columnHelp || ({});
70 const FIRST_COL_HELP = 'Click an entry to open it.';
71 const optionLabel = (f, c) => c === 'All' ? 'All ' + plural(f.label.toLowerCase()) : c;
72 const nounText = noun || 'entries';
73 const placeholderText = placeholder || 'Filter this reference';
74 const rootRef = useRef(null);
75 const tablesRef = useRef(null);
76 const searchRef = useRef(null);
77 const menuRef = useRef({});
78 const [q, qRef, setQ] = useLive('');
79 const [sel, selRef, setSel] = useLive({});
80 const [sortBy, sortRef, setSortBy] = useLive(null);
81 const [menuOpen, menuOpenRef, setMenu] = useLive(null);
82 const [facetList, setFacetList] = useState([]);
83 const [firstHead, setFirstHead] = useState('');
84 const [counts, setCounts] = useState({
85 shown: 0,
86 total: 0
87 });
88 const [disabled, setDisabled] = useState(false);
89 const menuBtn = name => menuRef.current[name] ? menuRef.current[name].querySelector(':scope > button') : null;
90 const menuList = name => menuRef.current[name] ? menuRef.current[name].querySelector('[role="listbox"]') : null;
91 const closeMenu = name => {
92 setMenu(null);
93 const btn = menuBtn(name);
94 if (btn) btn.focus();
95 };
96 const focusSelected = name => {
97 const list = menuList(name);
98 if (!list) return;
99 const btn = list.querySelector('button[aria-selected="true"]') || list.querySelector('button');
100 if (btn) btn.focus();
101 };
102 const setFacet = (name, value) => {
103 setSel(Object.assign({}, selRef.current, {
104 [name]: value
105 }));
106 apply(qRef.current);
107 closeMenu(name);
108 };
109 const sortTables = by => {
110 (tablesRef.current || []).forEach(tab => {
111 const t = tab.el;
112 const idx = tab.heads.indexOf(by);
113 const body = t.querySelector('tbody');
114 if (idx < 0 || !body) return;
115 const rows = [...body.querySelectorAll('tr')];
116 const keyOf = r => r.children[idx] ? r.children[idx].textContent.trim().toLowerCase() : '';
117 const cmp = cmpValues(by);
118 rows.map((r, i) => ({
119 r,
120 i: Number(r.dataset.sfIndex !== undefined ? r.dataset.sfIndex : i),
121 k: keyOf(r)
122 })).sort((a, b) => cmp(a.k, b.k) || a.i - b.i).forEach(x => body.appendChild(x.r));
123 [...t.querySelectorAll('thead th')].forEach((h, i) => {
124 const sortable = tab.heads[i] === tab.heads[0] || facetNames.indexOf(tab.heads[i]) > -1;
125 if (sortable) h.setAttribute('aria-sort', i === idx ? 'ascending' : 'none'); else h.removeAttribute('aria-sort');
126 });
127 });
128 };
129 const scan = () => {
130 const tables = [];
131 let el = rootRef.current ? rootRef.current.nextElementSibling : null;
132 while (el) {
133 if (el.tagName === 'H2' || el.querySelector(':scope > h2')) break;
134 const found = el.tagName === 'TABLE' ? [el] : [...el.querySelectorAll('table')];
135 found.forEach(t => {
136 const headCells = [...t.querySelectorAll('thead th, thead td')];
137 const heads = headCells.map(h => h.textContent.trim().toLowerCase());
138 if (heads.length === 0) return;
139 const facetIdx = {};
140 heads.forEach((h, i) => {
141 if (facetNames.indexOf(h) > -1) facetIdx[h] = i;
142 });
143 if (!t.dataset.sfDecorated) {
144 t.dataset.sfDecorated = '1';
145 headCells.forEach((h, i) => {
146 const text = i === 0 ? help[heads[0]] || FIRST_COL_HELP : help[heads[i]];
147 if (text) h.title = text;
148 });
149 }
150 const rows = [...t.querySelectorAll('tbody tr')].map((r, i) => {
151 if (r.dataset.sfIndex === undefined) r.dataset.sfIndex = String(i);
152 const cells = r.querySelectorAll('td');
153 const fv = {};
154 Object.keys(facetIdx).forEach(h => {
155 fv[h] = cells[facetIdx[h]] ? cells[facetIdx[h]].textContent.trim() : '';
156 });
157 return {
158 el: r,
159 text: [...cells].map(c => c.textContent).join(' ').toLowerCase(),
160 facets: fv,
161 anchors: [...r.querySelectorAll('a[href^="#"]')].map(a => a.getAttribute('href').slice(1)),
162 ids: [...r.querySelectorAll('[id]')].map(n => n.id)
163 };
164 });
165 tables.push({
166 el: t,
167 box: t.closest('[data-table-wrapper]') || t,
168 rows,
169 heads
170 });
171 });
172 el = el.nextElementSibling;
173 }
174 tablesRef.current = tables;
175 if (sortRef.current) sortTables(sortRef.current);
176 return tables;
177 };
178 const apply = query => {
179 let tables = tablesRef.current || scan();
180 if (tables.some(t => !t.el.isConnected)) tables = scan();
181 const needle = query.trim().toLowerCase();
182 const sel = selRef.current;
183 const activeFacets = Object.keys(sel).filter(h => sel[h] && sel[h] !== 'All');
184 const show = (el, on) => {
185 const want = on ? '' : 'none';
186 if (el.style.display !== want) el.style.display = want;
187 };
188 let total = 0;
189 let shown = 0;
190 const visibleTargets = new Set();
191 tables.forEach(t => {
192 let tableVisible = 0;
193 t.rows.forEach(row => {
194 total += 1;
195 const catOk = activeFacets.every(h => {
196 const v = row.facets[h];
197 return v === sel[h] || v === '' || v === undefined;
198 });
199 const match = catOk && (needle === '' || row.text.includes(needle));
200 show(row.el, match);
201 if (match) {
202 tableVisible += 1;
203 row.anchors.forEach(a => visibleTargets.add(a));
204 }
205 });
206 show(t.box, !(t.rows.length > 0 && tableVisible === 0));
207 shown += tableVisible;
208 });
209 if (shown < total && visibleTargets.size > 0) {
210 tables.forEach(t => {
211 t.rows.forEach(row => {
212 if (row.el.style.display === 'none' && row.ids.some(id => visibleTargets.has(id))) {
213 show(row.el, true);
214 show(t.box, true);
215 shown += 1;
216 }
217 });
218 });
219 }
220 setCounts({
221 shown,
222 total
223 });
224 return total;
225 };
226 const deriveFacets = tables => {
227 const seen = {};
228 tables.forEach(t => t.rows.forEach(r => {
229 Object.keys(r.facets).forEach(h => {
230 if (!seen[h]) seen[h] = [];
231 if (r.facets[h] && seen[h].indexOf(r.facets[h]) === -1) seen[h].push(r.facets[h]);
232 });
233 }));
234 const list = facetNames.filter(h => seen[h] && seen[h].length > 0).map(h => ({
235 name: h,
236 label: cap(h),
237 values: seen[h].sort(cmpValues(h))
238 }));
239 setFacetList(list);
240 const first = tables[0] ? tables[0].heads[0] : '';
241 setFirstHead(first);
242 if (!sortRef.current && first) {
243 setSortBy(first);
244 sortTables(first);
245 }
246 const init = {};
247 list.forEach(f => {
248 init[f.name] = selRef.current[f.name] || 'All';
249 });
250 setSel(init);
251 };
252 const onChange = value => {
253 setQ(value);
254 apply(value);
255 };
256 const clearAll = () => {
257 const next = {};
258 Object.keys(selRef.current).forEach(k => {
259 next[k] = 'All';
260 });
261 setSel(next);
262 setQ('');
263 apply('');
264 if (searchRef.current) searchRef.current.focus();
265 };
266 useEffect(() => {
267 const tables = scan();
268 deriveFacets(tables);
269 const total = apply('');
270 let retryTimer;
271 if (total === 0) {
272 retryTimer = setTimeout(() => {
273 tablesRef.current = null;
274 if (apply(qRef.current) > 0) deriveFacets(tablesRef.current); else setDisabled(true);
275 }, 500);
276 }
277 const onKey = e => {
278 if (e.key === 'Escape' && menuOpenRef.current !== null) closeMenu(menuOpenRef.current);
279 if (!searchRef.current) return;
280 if (e.metaKey || e.ctrlKey || e.altKey) return;
281 const active = document.activeElement;
282 const tag = active && active.tagName;
283 const editable = active && active.isContentEditable;
284 const interactive = tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || tag === 'BUTTON' || tag === 'A' || editable || active && active.getAttribute && active.getAttribute('role');
285 if (e.key === '/' && !interactive) {
286 const r = rootRef.current ? rootRef.current.getBoundingClientRect() : null;
287 if (r && r.bottom > 0 && r.top < (window.innerHeight || 0)) {
288 e.preventDefault();
289 setMenu(null);
290 searchRef.current.focus();
291 }
292 }
293 if (e.key === 'Escape' && menuOpenRef.current === null && active === searchRef.current) {
294 onChange('');
295 searchRef.current.blur();
296 }
297 };
298 const onDocClick = e => {
299 const open = menuOpenRef.current;
300 if (open !== null && menuRef.current[open] && !menuRef.current[open].contains(e.target)) setMenu(null);
301 };
302 window.addEventListener('keydown', onKey);
303 document.addEventListener('mousedown', onDocClick);
304 return () => {
305 if (retryTimer) clearTimeout(retryTimer);
306 window.removeEventListener('keydown', onKey);
307 document.removeEventListener('mousedown', onDocClick);
308 (tablesRef.current || []).forEach(t => {
309 t.box.style.display = '';
310 t.rows.forEach(row => {
311 row.el.style.display = '';
312 });
313 });
314 };
315 }, []);
316 useEffect(() => {
317 if (menuOpen !== null) focusSelected(menuOpen);
318 }, [menuOpen]);
319 if (disabled) return null;
320 const facetActive = Object.keys(sel).some(h => sel[h] && sel[h] !== 'All');
321 const sortOptions = [firstHead].concat(facetList.map(f => f.name)).filter((h, i, a) => h && a.indexOf(h) === i);
322 return <>
323 <style>{`
324 .sf-root {
325 --sf-accent: #D97757;
326 --sf-bg: #fff;
327 --sf-border: #E8E6DC;
328 --sf-text: #141413;
329 --sf-text-3: #73726C;
330 --sf-text-4: #9C9A92;
331 }
332 .dark .sf-root {
333 --sf-bg: #1a1918;
334 --sf-border: #3a3936;
335 --sf-text: #e8e6dc;
336 --sf-text-3: #9c9a92;
337 --sf-text-4: #73726c;
338 }
339 .sf-root .sf-end {
340 position: absolute;
341 right: 10px;
342 top: 50%;
343 transform: translateY(-50%);
344 }
345 .sf-root .sf-x {
346 background: none;
347 border: none;
348 cursor: pointer;
349 color: var(--sf-text-3);
350 font-size: 14px;
351 padding: 2px 4px;
352 line-height: 1;
353 }
354 `}</style>
355 <div ref={rootRef} className="sf-root" style={{
356 margin: '16px 0 8px'
357 }}>
358 <div style={{
359 display: 'flex',
360 gap: '8px',
361 flexWrap: 'wrap',
362 alignItems: 'center'
363 }}>
364 <div style={{
365 position: 'relative',
366 flex: '1 1 260px',
367 maxWidth: '480px'
368 }}>
369 <input ref={searchRef} value={q} onChange={e => onChange(e.target.value)} placeholder={placeholderText} aria-label={placeholderText} style={{
370 width: '100%',
371 padding: '8px 56px 8px 12px',
372 borderRadius: '8px',
373 border: '1px solid var(--sf-border)',
374 background: 'var(--sf-bg)',
375 color: 'var(--sf-text)',
376 fontSize: '14px',
377 outline: 'none',
378 boxSizing: 'border-box'
379 }} />
380 {q ? <button type="button" onClick={() => {
381 onChange('');
382 if (searchRef.current) searchRef.current.focus();
383 }} aria-label="Clear text" className="sf-end sf-x">
384 ×
385 </button> : <span className="sf-end" style={{
386 fontFamily: 'var(--font-mono, ui-monospace, monospace)',
387 fontSize: '11px',
388 color: 'var(--sf-text-4)',
389 border: '1px solid var(--sf-border)',
390 borderRadius: '3px',
391 padding: '0 5px',
392 pointerEvents: 'none'
393 }}>
394 /
395 </span>}
396 </div>
397 {facetList.map(f => {
398 const cur = sel[f.name] || 'All';
399 const isOpen = menuOpen === f.name;
400 return <div key={f.name} ref={el => {
401 menuRef.current[f.name] = el;
402 }} style={{
403 position: 'relative'
404 }}>
405 <button type="button" onClick={() => setMenu(isOpen ? null : f.name)} onKeyDown={e => {
406 if (e.key === 'ArrowDown') {
407 e.preventDefault();
408 if (!isOpen) setMenu(f.name); else focusSelected(f.name);
409 }
410 }} aria-haspopup="listbox" aria-expanded={isOpen} style={{
411 display: 'flex',
412 alignItems: 'center',
413 gap: '8px',
414 padding: cur !== 'All' ? '8px 30px 8px 12px' : '8px 12px',
415 borderRadius: '8px',
416 border: '1px solid ' + (cur !== 'All' ? 'var(--sf-accent)' : 'var(--sf-border)'),
417 background: 'var(--sf-bg)',
418 color: cur === 'All' ? 'var(--sf-text-3)' : 'var(--sf-text)',
419 fontSize: '13.5px',
420 cursor: 'pointer',
421 whiteSpace: 'nowrap',
422 maxWidth: '260px'
423 }}>
424 <span style={{
425 overflow: 'hidden',
426 textOverflow: 'ellipsis'
427 }}>
428 {f.label + ': ' + optionLabel(f, cur)}
429 </span>
430 <span aria-hidden="true" style={{
431 fontSize: '9px',
432 color: 'var(--sf-text-4)',
433 transform: isOpen ? 'rotate(180deg)' : 'none',
434 transition: 'transform 120ms'
435 }}>
436 ▼
437 </span>
438 </button>
439 {cur !== 'All' && <button type="button" onClick={() => setFacet(f.name, 'All')} aria-label={'Clear ' + f.label + ' filter'} title={'Clear ' + f.label + ' filter'} className="sf-end sf-x">
440 ×
441 </button>}
442 {isOpen && <div role="listbox" aria-label={f.label} onKeyDown={e => {
443 const items = [...e.currentTarget.querySelectorAll('button')];
444 const idx = items.indexOf(document.activeElement);
445 if (e.key === 'ArrowDown') {
446 e.preventDefault();
447 (items[idx + 1] || items[0]).focus();
448 } else if (e.key === 'ArrowUp') {
449 e.preventDefault();
450 (items[idx - 1] || items[items.length - 1]).focus();
451 } else if (e.key === 'Home') {
452 e.preventDefault();
453 if (items[0]) items[0].focus();
454 } else if (e.key === 'End') {
455 e.preventDefault();
456 if (items[items.length - 1]) items[items.length - 1].focus();
457 } else if (e.key === 'Tab') {
458 closeMenu(f.name);
459 }
460 }} style={{
461 position: 'absolute',
462 top: 'calc(100% + 6px)',
463 left: 0,
464 zIndex: 1000,
465 minWidth: '260px',
466 maxHeight: '340px',
467 overflowY: 'auto',
468 background: 'var(--sf-bg)',
469 border: '1px solid var(--sf-border)',
470 borderRadius: '10px',
471 boxShadow: '0 8px 24px rgba(0,0,0,0.12)',
472 padding: '5px'
473 }}>
474 {['All'].concat(f.values).map(c => {
475 const selected = cur === c;
476 return <button key={c} role="option" aria-selected={selected} tabIndex={-1} onClick={() => setFacet(f.name, c)} style={{
477 display: 'flex',
478 alignItems: 'center',
479 gap: '8px',
480 width: '100%',
481 textAlign: 'left',
482 padding: '7px 10px',
483 borderRadius: '6px',
484 border: 'none',
485 background: 'transparent',
486 color: selected ? 'var(--sf-accent)' : 'var(--sf-text)',
487 fontWeight: selected ? 600 : 400,
488 fontSize: '13.5px',
489 cursor: 'pointer'
490 }}>
491 <span aria-hidden="true" style={{
492 width: '14px',
493 color: 'var(--sf-accent)',
494 flexShrink: 0
495 }}>
496 {selected ? '✓' : ''}
497 </span>
498 {optionLabel(f, c)}
499 </button>;
500 })}
501 </div>}
502 </div>;
503 })}
504 {sortOptions.length > 1 && <div role="group" aria-label="Sort by" style={{
505 display: 'flex',
506 alignItems: 'center',
507 gap: '4px',
508 fontSize: '13px',
509 color: 'var(--sf-text-3)',
510 whiteSpace: 'nowrap'
511 }}>
512 <span style={{
513 marginRight: '4px'
514 }}>Sort by</span>
515 {sortOptions.map(o => {
516 const on = sortBy === o;
517 return <button key={o} type="button" aria-pressed={on} onClick={() => {
518 setSortBy(o);
519 sortTables(o);
520 }} style={{
521 padding: '6px 10px',
522 borderRadius: '8px',
523 border: '1px solid ' + (on ? 'var(--sf-accent)' : 'var(--sf-border)'),
524 background: 'var(--sf-bg)',
525 color: on ? 'var(--sf-text)' : 'var(--sf-text-3)',
526 fontSize: '13px',
527 cursor: 'pointer'
528 }}>
529 {o.charAt(0).toUpperCase() + o.slice(1)}
530 </button>;
531 })}
532 </div>}
533 </div>
534 <div aria-live="polite" style={{
535 margin: '8px 0 0',
536 fontSize: '13px',
537 color: 'var(--sf-text-3)',
538 minHeight: '1px'
539 }}>
540 {q.trim() === '' && !facetActive ? <>{counts.total} {nounText}</> : counts.shown === 0 ? <>
541 {q.trim() === '' ? 'No ' + nounText + ' match the selected filters.' : facetActive ? 'No ' + nounText + ' match \u201c' + q + '\u201d with the selected filters.' : 'No ' + nounText + ' match \u201c' + q + '\u201d.'}{' '}
542 <button type="button" onClick={clearAll} style={{
543 background: 'none',
544 border: 'none',
545 padding: 0,
546 color: 'var(--sf-accent)',
547 cursor: 'pointer',
548 font: 'inherit',
549 textDecoration: 'underline'
550 }}>
551 Clear filters
552 </button>
553 {children ? <> {children}</> : null}
554 </> : <>
555 Showing {counts.shown} of {counts.total} {nounText}
556 </>}
557 </div>
558 </div>
559 </>;
560};
561
562<BackToIndex href="#all-settings" label="Back to index" />
5[Back to index](#all-settings)
5636
5647This reference page lists each key Claude Code reads from a settings file, plus the [short group of keys](#global-config-settings) it keeps in `~/.claude.json` instead. To pick a file, or check precedence, start with [Settings files and precedence](/docs/en/settings).
5658
566<span id="available-settings" />
567
568<span id="scopes" />
569
570<span id="all-settings" />
571
5729## Settings index
57310
57411Every key below links to its entry. Scope lists the [files](/docs/en/settings#settings-files-and-who-they-affect) it can go in: `User` is `~/.claude/settings.json`, `Project` is `.claude/settings.json`, `Local` is `.claude/settings.local.json`, and `Managed` is [what your organization deploys](/docs/en/managed-settings). `Any file` means all four, and `Global config` means [`~/.claude.json`](#global-config-settings).
575
576<ReferenceFilter
577 noun="settings"
578 placeholder="Filter settings by key or purpose"
579 facetOrder={{ scope: ["Any file", "User, local, or managed", "User or managed", "User", "Managed", "Global config"] }}
580 columnHelp={{
581topic: "The section of this page that holds the entry. Use Sort by to group the table by topic.",
582scope: "Which settings files can set the key: user (~/.claude/settings.json), project (.claude/settings.json), local (.claude/settings.local.json), or managed (deployed by your organization). Global config keys are in ~/.claude.json instead.",
583}}
584/>
58512
58613| Key | Description | Topic | Scope |
58714| :- | :- | :- | :- |
from line 574
1147574}
1148575```
1149576
1150<span id="modelpicker-options" />
1151
1152<span id="modelpicker-replacebuiltinoptions" />
1153
1154577#### Fields for `modelPicker`
1155578
1156579The key takes two fields, one for the rows themselves and one for whether they replace the built-in lineup or add to it.
from line 627
1204627
1205628For the steps, including how to confirm the rates are in effect, see [Report spend at your contracted rates](/docs/en/costs#report-spend-at-your-contracted-rates).
1206629
1207<span id="modelpricing-multiplier" />
1208
1209<span id="modelpricing-overrides" />
1210
1211630#### Fields for `modelPricing`
1212631
1213632| Field | Type | What it does |
from line 976
1557976 }
1558977}
1559978```
1560
1561<span id="exclude-sensitive-files" />
1562979
1563980### `permissions.deny`
1564981
from line 1703
22861703Paths use the same [prefixes](#sandbox-path-prefixes) as the `sandbox.filesystem.*` settings, and Claude Code merges the arrays from every settings scope the session loads. [Protect credentials](/docs/en/sandboxing#protect-credentials) covers what still applies from sources you exclude with `--setting-sources`. `mask` entries require Claude Code v2.1.221 or later.
22871704
22881705`mask` substitution runs only through the sandbox proxy, so set [`sandbox.network.tlsTerminate`](#sandbox-network-tlsterminate), or [`allowPlaintextInject`](#sandbox-credentials-allowplaintextinject) for plain-HTTP test networks. `mask` applies to a single file, so list each credential file individually. Claude Code accepts but ignores the `mask` fields on a `deny` entry. [Mask credentials](/docs/en/sandboxing#mask-credentials) covers which settings sources are honored, and [Mask credential files](/docs/en/sandboxing#mask-credential-files) covers when an entry falls back to `deny`.
2289
2290<span id="sandbox-credentials-files-extract" />
2291
2292<span id="sandbox-credentials-files-onextractnomatch" />
2293
2294<span id="sandbox-credentials-files-decode" />
2295
2296<span id="sandbox-credentials-files-maskclaims" />
2297
2298<span id="sandbox-credentials-files-maskduplicates" />
2299
2300<span id="sandbox-credentials-files-injecthosts" />
23011706
23021707#### Mask fields for files
23031708
from line 1764
23591764The `name` must start with a letter or underscore and contain only letters, digits, and underscores. Claude Code merges the arrays from every settings scope the session loads, and applies `deny` when the same variable appears with both modes. [Protect credentials](/docs/en/sandboxing#protect-credentials) covers what still applies from sources you exclude with `--setting-sources`.
23601765
23611766`mask` substitution runs only through the sandbox proxy, so set [`sandbox.network.tlsTerminate`](#sandbox-network-tlsterminate), or [`allowPlaintextInject`](#sandbox-credentials-allowplaintextinject) for plain-HTTP test networks; see [Mask credentials](/docs/en/sandboxing#mask-credentials). Claude Code accepts but ignores the `mask` fields on a `deny` entry.
2362
2363<span id="sandbox-credentials-envvars-extract" />
2364
2365<span id="sandbox-credentials-envvars-onextractnomatch" />
2366
2367<span id="sandbox-credentials-envvars-decode" />
2368
2369<span id="sandbox-credentials-envvars-maskclaims" />
2370
2371<span id="sandbox-credentials-envvars-injecthosts" />
23721767
23731768#### Mask fields for environment variables
23741769
from line 2139
27442139
27452140When more than one honored source sets it, Claude Code uses the value from the highest-precedence source: managed settings, then the `--settings` flag, then user settings.
27462141
2747<span id="context-and-memory" />
2748
27492142## Memory and context
27502143
27512144Control what Claude Code loads into context, how it compacts, and where it keeps memory and plans. See [Manage context](/docs/en/context-window) and [Memory](/docs/en/memory).
from line 2261
28682261```
28692262
28702263Exclusions apply only to user, project, and local memory files; managed policy CLAUDE.md files can't be excluded.
2871
2872<span id="environment-variables" />
28732264
28742265### `env`
28752266
from line 2350
29592350
29602351### `idleCompaction`
29612352
2962Idle compaction [compacts](/docs/en/context-window#what-survives-compaction) a long conversation that you've stepped away from, shortly before its prompt cache expires. Your next message then sends a summary instead of the whole conversation. When you come back, the conversation shows `Compacted while idle, before the prompt cache expired`.
2353Idle compaction [compacts](/docs/en/context-window#what-survives-compaction) a long conversation that you've stepped away from, shortly before its prompt cache expires. Your next message then sends a summary instead of the whole conversation. When you come back, the conversation shows a line that starts with `Compacted while idle, before the prompt cache expired`.
29632354
29642355Idle compaction is on by default for conversations that meet all of these conditions:
29652356
from line 2375
29842375}
29852376```
29862377
2378To turn idle compaction off or on from inside a session, run `/config` and change the **Idle compaction** row. Your choice is saved to your user settings and applies right away. The row requires Claude Code v2.1.302 or later. If you run one of those versions and `/config` doesn't show the row, check for these causes:
2379
2380* **Another settings source sets the key**: a value in managed settings, the `--settings` flag, or a project or local settings file overrides your user settings. Change the key in that source instead
2381* **Feature flags are unavailable**: where Claude Code can't [fetch feature flags from Anthropic](/docs/en/env-vars#features-that-need-feature-flag-fetching), idle compaction doesn't run, so there is nothing to turn off
2382
29872383The key requires Claude Code v2.1.290 or later. On an earlier version, which ignores this key, turn off [`autoCompactEnabled`](#autocompactenabled) to stop idle compaction.
29882384
29892385#### Change the idle compaction threshold
from line 2449
30532449
30542450### `taskOutputMaxChars`
30552451
3056<Warning>
3057 Removed in v2.1.277, together with the `TaskOutput` tool it sized. Setting it has no effect on current versions. Claude reads a background task's [output file](/docs/en/tools-reference#background-commands) with `Read` instead.
3058</Warning>
2452> [!WARNING]
2453>
2454> Removed in v2.1.277, together with the `TaskOutput` tool it sized. Setting it has no effect on current versions. Claude reads a background task's [output file](/docs/en/tools-reference#background-commands) with `Read` instead.
30592455
30602456Through v2.1.276, you set this key to the number of characters of a [background task's](/docs/en/tools-reference#background-commands) output that Claude received inline when it read the task with the `TaskOutput` tool.
30612457
from line 2636
32402636```
32412637
32422638See [Emoji shortcodes](/docs/en/interactive-mode#emoji-shortcodes). Requires Claude Code v2.1.217 or later.
3243
3244<span id="file-suggestion-settings" />
32452639
32462640### `fileSuggestion`
32472641
from line 2680
32862680# Replace your-repo-file-index with your own file search command
32872681your-repo-file-index --query "$query" | head -20
32882682```
3289
3290<span id="footer-link-badges" />
32912683
32922684### `footerLinksRegexes`
32932685
from line 2724
33322724
33332725### `keybindingFlavor`
33342726
3335<Warning>
3336 Deprecated since v2.1.261 and has no effect. The prompt's word-editing keys always [follow readline conventions](/docs/en/interactive-mode#make-ctrl-w-delete-back-to-whitespace), as in Bash. Claude Code still accepts `keybindingFlavor`, so a settings file that sets it stays valid.
3337</Warning>
2727> [!WARNING]
2728>
2729> Deprecated since v2.1.261 and has no effect. The prompt's word-editing keys always [follow readline conventions](/docs/en/interactive-mode#make-ctrl-w-delete-back-to-whitespace), as in Bash. Claude Code still accepts `keybindingFlavor`, so a settings file that sets it stays valid.
33382730
33392731In v2.1.238 through v2.1.260, setting it to `"readline"` made `Ctrl+W` delete back to the previous whitespace instead of only the previous word.
33402732
from line 3231
38393231
38403232### `voiceEnabled`
38413233
3842<Warning>
3843 Deprecated since v2.1.92, when the [`voice`](#voice) object replaced it. Claude Code still reads it so older settings files keep working, but new configurations should set `voice.enabled`.
3844</Warning>
3234> [!WARNING]
3235>
3236> Deprecated since v2.1.92, when the [`voice`](#voice) object replaced it. Claude Code still reads it so older settings files keep working, but new configurations should set `voice.enabled`.
38453237
38463238Turn voice dictation on with the single Boolean form that predates the `voice` object. When both are set, `voice.enabled` applies.
38473239
from line 3268
38763268## Git and attribution
38773269
38783270Control the attribution Claude Code adds to commits and pull requests and how it works with git.
3879
3880<span id="attribution-settings" />
38813271
38823272### `attribution`
38833273
from line 3297
39073297
39083298### `includeCoAuthoredBy`
39093299
3910<Warning>
3911 Deprecated since v2.0.62, when [`attribution`](#attribution) replaced it. Claude Code still reads it, but new configurations should set `attribution`.
3912</Warning>
3300> [!WARNING]
3301>
3302> Deprecated since v2.0.62, when [`attribution`](#attribution) replaced it. Claude Code still reads it, but new configurations should set `attribution`.
39133303
39143304Use [`attribution`](#attribution) instead, which replaces this key and lets you change or hide the commit trailer, the pull request text, and the session link separately. Claude Code still honors `includeCoAuthoredBy: false` from settings files that predate `attribution`, but ignores it once you set `attribution.commit` or `attribution.pr`.
39153305
from line 3410
40203410 }
40213411}
40223412```
4023
4024<span id="hook-configuration" />
4025
4026<span id="hook-and-skill-settings" />
40273413
40283414## Hooks and automation
40293415
from line 3621
42353621```
42363622
42373623Requires Claude Code v2.1.219 or later; on v2.1.202 through v2.1.218, set the guideline in `/config` instead.
4238
4239<span id="plugin-configuration" />
4240
4241<span id="manage-plugins" />
4242
4243<span id="plugin-settings" />
42443624
42453625## Plugins and skills
42463626
from line 4028
46484028
46494029### `strictPluginOnlyCustomization.hooks`
46504030
4651Lock the `hooks` surface. Claude Code stops running hooks from user, project, and local `settings.json`, and keeps running plugin hooks and hooks in managed settings.
4031Lock the `hooks` surface:
4032
4033* **Stops running**:
4034 * Hooks from user, project, and local `settings.json`
4035 * Frontmatter hooks in skills, custom commands, and agents, from the sources that a [`skills`](#strictpluginonlycustomization-skills) or [`agents`](#strictpluginonlycustomization-agents) lock would block
4036* **Keeps running**: plugin hooks and hooks in managed settings
4037
4038Skills, custom commands, and agents whose frontmatter hooks stop running still load while their own surface isn't locked.
46524039
46534040* **Scope**: [`Managed`](#scopes)
46544041* **Type**: the string `"hooks"` in the [`strictPluginOnlyCustomization`](#strictpluginonlycustomization) array
from line 4572
51854572}
51864573```
51874574
5188<span id="worktree-settings" />
5189
51904575### `worktree`
51914576
51924577Configure how Claude Code creates and manages [git worktrees](/docs/en/worktrees) for `--worktree`, the `EnterWorktree` tool, and isolated subagents and background sessions.
from line 4734
53494734
53504735### `disableArtifact`
53514736
5352<Warning>
5353 Deprecated, and replaced by [`enableArtifact`](#enableartifact). Claude Code still honors `disableArtifact: true` as equivalent to `enableArtifact: false`, and ignores `disableArtifact: false`.
5354</Warning>
4737> [!WARNING]
4738>
4739> Deprecated, and replaced by [`enableArtifact`](#enableartifact). Claude Code still honors `disableArtifact: true` as equivalent to `enableArtifact: false`, and ignores `disableArtifact: false`.
53554740
53564741Use [`enableArtifact`](#enableartifact) instead to turn off the [Artifact](/docs/en/artifacts) tool, which publishes session output as a private web page on claude.ai. When you turn the **Artifacts** row off in `/config`, Claude Code writes `enableArtifact` to your user settings and clears this key.
53574742
from line 4950
55654950A value that Desktop can't read as a list of hosts, such as `true` or an object, counts as an empty array until you correct it, except `null`, which counts as unset. Requires Claude Desktop v2.26454.0 or later.
55664951
55674952If you set [`managedSourcesBehavior`](#managedsourcesbehavior) to `"merge"` in your highest-ranked source, Desktop combines the lists from every [admin source](/docs/en/managed-settings#how-claude-code-combines-managed-sources) and allows a host that matches any of them. If you set an empty array in one source, SSH sessions stay on for the hosts another source lists.
5568
5569<span id="authentication-and-login" />
55704953
55714954## Authentication and providers
55724955
from line 5296
59135296
59145297The desktop app ignores any other value, and a value that isn't a Boolean, such as the string `"true"` or `1`, also logs a warning.
59155298
5916<span id="data-and-privacy" />
5917
59185299## Privacy and telemetry
59195300
59205301Control how long Claude Code keeps session data and what it sends. The switches that turn off usage metrics and error reports are environment variables, not settings keys: set `DISABLE_TELEMETRY`, `DISABLE_ERROR_REPORTING`, or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` in the [`env`](#env) key or in the shell. [Telemetry services](/docs/en/data-usage#telemetry-services) says what each one stops. Two exceptions turn off from a settings file: [`feedbackDrafts`](#feedbackdrafts) below for Claude-drafted feedback, and [`feedbackSurveyRate`](#feedbacksurveyrate) below for the session survey.
from line 5384
60035384```
60045385
60055386With the check skipped, WebFetch attempts any URL without consulting the blocklist, so pair it with [`WebFetch` permission rules](/docs/en/permissions#webfetch) if you need to restrict which domains Claude can reach.
6006
6007<span id="managed-policy" />
60085387
60095388## Enterprise and managed settings
60105389
from line 5498
61195498
61205499This key has no effect when no admin-deployed managed tier exists: the host's settings then apply as the only managed tier, still filtered to restrictive values. For the filter's limits and how the managed sources interact, see [Parent settings from embedding hosts](/docs/en/managed-settings#parent-settings-from-embedding-hosts) and [Restrict parent settings](/docs/en/claude-apps-gateway#restrict-parent-settings).
61215500
6122<span id="compute-managed-settings-with-a-policy-helper" />
6123
61245501### `policyHelper`
61255502
61265503Run an executable you deploy that computes managed settings at startup, so you can derive policy from device posture, identity, or a remote service instead of a static file. Claude Code runs the helper before it accepts the first prompt and treats the settings it emits as the managed settings for the session.
from line 5821
64445821
64455822### `permissionExplainerEnabled`
64465823
6447<Warning>
6448 Removed in v2.1.257, together with the `Ctrl+E` command explanation on Bash and PowerShell permission prompts. Setting it has no effect on current versions.
6449</Warning>
5824> [!WARNING]
5825>
5826> Removed in v2.1.257, together with the `Ctrl+E` command explanation on Bash and PowerShell permission prompts. Setting it has no effect on current versions.
64505827
64515828Through v2.1.256, you could press `Ctrl+E` on a Bash or PowerShell permission prompt to see a model-generated explanation of the command, and set this key to `false` to turn that shortcut off.
64525829
from line 5851
64745851
64755852### `teammateDefaultModel`
64765853
6477<Warning>
6478 Removed in v2.1.234, together with its `/config` row **Default teammate model**. Setting it has no effect on current versions.
6479</Warning>
5854> [!WARNING]
5855>
5856> Removed in v2.1.234, together with its `/config` row **Default teammate model**. Setting it has no effect on current versions.
64805857
64815858Through v2.1.233, you set this key to the model for [agent team](/docs/en/agent-teams#specify-teammates-and-models) teammates your prompt didn't name a model for: an alias such as `"sonnet"`, or `null` to follow the lead's model. For the model Claude Code picks for such teammates now, see [specify teammates and models](/docs/en/agent-teams#specify-teammates-and-models).
64825859
64835860
No line in this hunk matches that.