6 6
7> Eine interaktive Simulation, wie sich das Kontextfenster von Claude Code während einer Sitzung füllt. Sehen Sie, was automatisch geladen wird, welche Kosten jeder Dateilesevorgang hat, und wann Regeln und Hooks ausgelöst werden.7> Eine interaktive Simulation, wie sich das Kontextfenster von Claude Code während einer Sitzung füllt. Sehen Sie, was automatisch geladen wird, welche Kosten jeder Dateilesevorgang hat, und wann Regeln und Hooks ausgelöst werden.
8 8
9Das Kontextfenster von Claude Code enthält alles, was Claude über Ihre Sitzung weiß: Ihre Anweisungen, die Dateien, die es liest, seine eigenen Antworten und Inhalte, die nie in Ihrem Terminal erscheinen. Die folgende Zeitleiste zeigt, was geladen wird und wann. Siehe [die schriftliche Aufschlüsselung](#what-the-timeline-shows) für denselben Inhalt als Liste.9export const ContextWindow = () => {
10 const MAX = 200000;
11 const STARTUP_END = 0.2;
12 {}
13 const EVENTS = useMemo(() => [{}, {
14 t: 0.015,
15 kind: 'auto',
16 label: 'System prompt',
17 tokens: 4200,
18 color: '#6B6964',
19 vis: 'hidden',
20 desc: 'Core instructions for behavior, tool use, and response formatting. Always loaded first. You never see it.',
21 link: null
22 }, {
23 t: 0.035,
24 kind: 'auto',
25 label: 'Auto memory (MEMORY.md)',
26 tokens: 680,
27 color: '#E8A45C',
28 vis: 'hidden',
29 desc: "Claude's notes to itself from previous sessions: build commands it learned, patterns it noticed, mistakes to avoid. The first 200 lines or 25KB, whichever comes first, are loaded into the conversation context.",
30 link: '/en/memory#auto-memory'
31 }, {
32 t: 0.06,
33 kind: 'auto',
34 label: 'Environment info',
35 tokens: 280,
36 color: '#6B6964',
37 vis: 'hidden',
38 desc: 'Working directory, platform, shell, OS version, and whether this is a git repo. Git branch, status, and recent commits load as a separate block at the very end of the system prompt.',
39 link: null
40 }, {
41 t: 0.08,
42 kind: 'auto',
43 label: 'MCP tools (deferred)',
44 tokens: 120,
45 color: '#9B7BC4',
46 vis: 'hidden',
47 desc: 'MCP tool names listed so Claude knows what is available. By default, full schemas stay deferred and Claude loads specific ones on demand via tool search when a task needs them. Set `ENABLE_TOOL_SEARCH=auto` to load schemas upfront when they fit within 10% of the context window, or `ENABLE_TOOL_SEARCH=false` to load everything.',
48 link: '/en/mcp#scale-with-mcp-tool-search'
49 }, {
50 t: 0.1,
51 kind: 'auto',
52 label: 'Skill descriptions',
53 tokens: 450,
54 color: '#D4A843',
55 vis: 'hidden',
56 noSurviveCompact: true,
57 desc: 'One-line descriptions of available skills so Claude knows what it can invoke. Full skill content loads only when Claude actually uses one. Skills with `disable-model-invocation: true` are not in this list. They stay completely out of context until you invoke them with `/name`. Unlike the rest of the startup content, this listing is not re-injected after `/compact`. Only skills you actually invoked get preserved.',
58 link: '/en/skills'
59 }, {
60 t: 0.12,
61 kind: 'auto',
62 label: '~/.claude/CLAUDE.md',
63 tokens: 320,
64 color: '#6A9BCC',
65 vis: 'hidden',
66 desc: 'Your global preferences. Applies to every project. Loaded alongside project instructions at the start of every conversation.',
67 link: '/en/memory#choose-where-to-put-claude-md-files'
68 }, {
69 t: 0.14,
70 kind: 'auto',
71 label: 'Project CLAUDE.md',
72 tokens: 1800,
73 color: '#6A9BCC',
74 vis: 'hidden',
75 desc: 'Project conventions, build commands, architecture notes. The most important file you can create. Lives in your project root, so your whole team gets the same instructions.',
76 tip: 'Keep it under 200 lines. Move reference content to skills or path-scoped rules so it only loads when needed.',
77 link: '/en/memory'
78 }, {}, {
79 t: 0.22,
80 kind: 'user',
81 label: 'Your prompt',
82 tokens: 45,
83 color: '#558A42',
84 vis: 'full',
85 desc: '"Fix the auth bug where users get 401 after token refresh"',
86 link: null
87 }, {}, {
88 t: 0.28,
89 kind: 'claude',
90 label: 'Read src/api/auth.ts',
91 tokens: 2400,
92 color: '#8A8880',
93 vis: 'brief',
94 desc: 'Main auth file. You see "Read auth.ts" in your terminal, but the 2,400 tokens of file content only Claude sees.',
95 tip: 'File reads dominate context usage. Be specific in prompts ("fix the bug in auth.ts") so Claude reads fewer files. For research-heavy tasks, use a subagent.',
96 link: null
97 }, {
98 t: 0.32,
99 kind: 'claude',
100 label: 'Read src/lib/tokens.ts',
101 tokens: 1100,
102 color: '#8A8880',
103 vis: 'brief',
104 desc: 'Following imports to the token module. Shown as a one-liner in your terminal.',
105 link: null
106 }, {
107 t: 0.35,
108 kind: 'auto',
109 label: 'Rule: api-conventions.md',
110 tokens: 380,
111 color: '#4A9B8E',
112 vis: 'brief',
113 desc: 'This rule in `.claude/rules/` has a `paths:` pattern matching `src/api/**`. It loaded automatically when Claude read a file in that directory. You see "Loaded .claude/rules/api-conventions.md" in your terminal, but not the rule content.',
114 link: '/en/memory#path-specific-rules'
115 }, {
116 t: 0.38,
117 kind: 'claude',
118 label: 'Read middleware.ts',
119 tokens: 1800,
120 color: '#8A8880',
121 vis: 'brief',
122 desc: 'Tracing the auth flow deeper.',
123 link: null
124 }, {
125 t: 0.41,
126 kind: 'claude',
127 label: 'Read auth.test.ts',
128 tokens: 1600,
129 color: '#8A8880',
130 vis: 'brief',
131 desc: 'Checking existing tests for expected behavior.',
132 link: null
133 }, {
134 t: 0.44,
135 kind: 'auto',
136 label: 'Rule: testing.md',
137 tokens: 290,
138 color: '#4A9B8E',
139 vis: 'brief',
140 desc: 'Another path-scoped rule, this one matching `*.test.ts` files. Triggered when Claude read auth.test.ts. Shown as a one-line "Loaded" notice.',
141 link: '/en/memory#path-specific-rules'
142 }, {
143 t: 0.47,
144 kind: 'claude',
145 label: 'grep "refreshToken"',
146 tokens: 600,
147 color: '#A09E96',
148 vis: 'brief',
149 desc: 'Search results across the codebase. You see the command ran, not the full output.',
150 link: null
151 }, {}, {
152 t: 0.53,
153 kind: 'claude',
154 label: "Claude's analysis",
155 tokens: 800,
156 color: '#D97757',
157 vis: 'full',
158 desc: 'Explains the bug: token invalidated too early in the rotation. This text appears in your terminal.',
159 link: null
160 }, {
161 t: 0.57,
162 kind: 'claude',
163 label: 'Edit auth.ts',
164 tokens: 400,
165 color: '#D97757',
166 vis: 'full',
167 desc: 'Fixes the token rotation order. The diff appears in your terminal.',
168 link: null
169 }, {
170 t: 0.59,
171 kind: 'hook',
172 label: 'Hook: prettier',
173 tokens: 120,
174 color: '#B8860B',
175 vis: 'hidden',
176 desc: 'A PostToolUse hook in `settings.json` runs prettier after every file edit and reports back via `hookSpecificOutput.additionalContext`. That field enters Claude\'s context. Plain stdout on exit 0 does not. It is written to the debug log only.',
177 tip: 'Output JSON with `additionalContext` to send info to Claude. For PostToolUse hooks, exit code 2 surfaces stderr as an error but cannot block since the tool already ran. Keep output concise since it enters context without truncation.',
178 link: '/en/hooks-guide'
179 }, {
180 t: 0.62,
181 kind: 'claude',
182 label: 'Edit auth.test.ts',
183 tokens: 600,
184 color: '#D97757',
185 vis: 'full',
186 desc: 'Adds a regression test for the fix. The diff appears in your terminal.',
187 link: null
188 }, {
189 t: 0.64,
190 kind: 'hook',
191 label: 'Hook: prettier',
192 tokens: 100,
193 color: '#B8860B',
194 vis: 'hidden',
195 desc: 'The same hook fires again for the test file. Every matching tool event triggers it.',
196 link: '/en/hooks-guide'
197 }, {
198 t: 0.67,
199 kind: 'claude',
200 label: 'npm test output',
201 tokens: 1200,
202 color: '#A09E96',
203 vis: 'brief',
204 desc: 'Runs the test suite. You see "Running npm test..." and the pass count, not the full 1,200 tokens of output.',
205 link: null
206 }, {
207 t: 0.70,
208 kind: 'claude',
209 label: 'Summary',
210 tokens: 400,
211 color: '#D97757',
212 vis: 'full',
213 desc: '"Fixed token rotation. Added regression test. All tests pass."',
214 link: null
215 }, {}, {
216 t: 0.72,
217 kind: 'user',
218 label: 'Your follow-up',
219 tokens: 40,
220 color: '#558A42',
221 vis: 'full',
222 desc: '"Use a subagent to research session timeout handling, then fix it"',
223 tip: 'Follow-ups add to the same context. Delegating research to a subagent keeps large file reads out of your main window.',
224 link: null
225 }, {
226 t: 0.79,
227 kind: 'claude',
228 label: 'Spawn research subagent',
229 tokens: 80,
230 color: '#D97757',
231 vis: 'brief',
232 desc: "Claude delegates the research to a subagent with a fresh, separate context window. It loads CLAUDE.md and the same MCP and skill setup, but starts without your conversation history or the main session's auto memory.",
233 link: '/en/sub-agents'
234 }, {
235 t: 0.795,
236 kind: 'sub',
237 label: 'System prompt',
238 tokens: 0,
239 subTokens: 900,
240 color: '#6B6964',
241 vis: 'hidden',
242 desc: "The subagent gets its own system prompt, shorter than the main session's. For the general-purpose agent, it's a brief prompt plus environment details. The main session's auto memory is not included. If a custom agent has memory: in its frontmatter, it loads its own separate MEMORY.md here instead.",
243 link: '/en/sub-agents#enable-persistent-memory'
244 }, {
245 t: 0.80,
246 kind: 'sub',
247 label: 'Project CLAUDE.md (own copy)',
248 tokens: 0,
249 subTokens: 1800,
250 color: '#6A9BCC',
251 vis: 'hidden',
252 desc: "The subagent loads CLAUDE.md too. Same file, same content, but it counts against the subagent's context, not yours. The built-in Explore and Plan agents skip this for a smaller context.",
253 link: '/en/sub-agents'
254 }, {
255 t: 0.805,
256 kind: 'sub',
257 label: 'MCP tools + skills',
258 tokens: 0,
259 subTokens: 970,
260 color: '#9B7BC4',
261 vis: 'hidden',
262 desc: "The subagent has access to the same MCP servers and skills. It gets most of the parent's tools, minus several that don't apply in a nested context, including plan-mode controls, background-task tools, and by default the Agent tool itself to prevent recursion.",
263 link: '/en/sub-agents'
264 }, {
265 t: 0.81,
266 kind: 'sub',
267 label: 'Task prompt from main',
268 tokens: 0,
269 subTokens: 120,
270 color: '#558A42',
271 vis: 'hidden',
272 desc: "Instead of a user prompt, the subagent receives the task Claude wrote for it: 'Research session timeout handling in this codebase.'",
273 link: '/en/sub-agents'
274 }, {
275 t: 0.82,
276 kind: 'sub',
277 label: 'Read session.ts',
278 tokens: 0,
279 subTokens: 2200,
280 color: '#8A8880',
281 vis: 'hidden',
282 desc: "Now the subagent does its work. This file read fills the subagent's context, not yours.",
283 link: '/en/sub-agents'
284 }, {
285 t: 0.825,
286 kind: 'sub',
287 label: 'Read timeouts.ts',
288 tokens: 0,
289 subTokens: 800,
290 color: '#8A8880',
291 vis: 'hidden',
292 desc: "Another file read in the subagent's separate context.",
293 link: '/en/sub-agents'
294 }, {
295 t: 0.83,
296 kind: 'sub',
297 label: 'Read config/*.ts',
298 tokens: 0,
299 subTokens: 3100,
300 color: '#8A8880',
301 vis: 'hidden',
302 desc: "The subagent can read as many files as it needs. None of this touches your main context.",
303 link: '/en/sub-agents'
304 }, {
305 t: 0.85,
306 kind: 'claude',
307 label: 'Subagent returns summary',
308 tokens: 420,
309 color: '#D97757',
310 vis: 'brief',
311 desc: "Only the subagent's final text response comes back to your context, plus a small metadata trailer with token counts and duration. The subagent read 6,100 tokens of files. You got a 420-token result. That's the context savings.",
312 link: '/en/sub-agents'
313 }, {
314 t: 0.86,
315 kind: 'claude',
316 label: "Claude's response",
317 tokens: 1200,
318 color: '#D97757',
319 vis: 'full',
320 desc: 'Analysis and fix for session timeouts. This text appears in your terminal.',
321 link: null
322 }, {}, {
323 t: 0.875,
324 kind: 'user',
325 label: '!git status',
326 tokens: 180,
327 color: '#558A42',
328 vis: 'full',
329 desc: "You ran a shell command with the ! prefix to see which files Claude modified. The command and its output both enter context as part of your message. Useful for grounding Claude in command output without Claude running it.",
330 link: '/en/interactive-mode#bash-mode-with-prefix'
331 }, {
332 t: 0.89,
333 kind: 'user',
334 label: '/commit-push',
335 tokens: 620,
336 color: '#558A42',
337 vis: 'brief',
338 desc: 'You invoked a skill that has `disable-model-invocation: true`. Its description was not in the skill index at startup, so it cost zero context until this moment. Now the full skill content loads and Claude follows its instructions to stage, commit, and push your changes.',
339 tip: 'Set `disable-model-invocation: true` on skills with side effects like committing, deploying, or sending messages. They stay out of context entirely until you need them.',
340 link: '/en/skills#control-who-invokes-a-skill'
341 }, {}, {
342 t: 0.93,
343 kind: 'compact',
344 label: '/compact',
345 tokens: 0,
346 color: '#D97757',
347 vis: 'brief',
348 desc: 'Replaces the conversation with a structured summary. You see a "Conversation compacted" message. The summarization happens without appearing in your terminal.',
349 link: '/en/how-claude-code-works#the-context-window'
350 }].filter(e => e.t !== undefined), []);
351 const VIS_META = {
352 hidden: {
353 label: 'Invisible in your terminal',
354 sub: 'This content does not appear in your terminal.'
355 },
356 brief: {
357 label: 'One-liner in your terminal',
358 sub: 'You see a brief mention, not the full content.'
359 },
360 full: {
361 label: 'Shown in your terminal',
362 sub: 'The actual content appears in your terminal.'
363 }
364 };
365 {}
366 const GATES = [{
367 at: 0.18,
368 kind: 'prompt',
369 text: 'Fix the auth bug where users get 401 after token refresh',
370 resumeTo: 0.22
371 }, {
372 at: 0.705,
373 kind: 'prompt',
374 text: 'Use a subagent to research session timeout handling, then fix it',
375 resumeTo: 0.72
376 }, {
377 at: 0.865,
378 kind: 'bang',
379 text: '!git status',
380 resumeTo: 0.875
381 }, {
382 at: 0.88,
383 kind: 'slash',
384 text: '/commit-push',
385 resumeTo: 0.89
386 }, {
387 at: 0.90,
388 kind: 'compact',
389 text: '/compact',
390 resumeTo: 1
391 }];
392 const KIND_META = {
393 auto: {
394 badge: 'auto',
395 detail: 'Auto-loaded',
396 badgeBg: 'rgba(94,93,89,0.15)',
397 badgeColor: '#8A8880'
398 },
399 user: {
400 badge: 'you',
401 detail: 'You typed this',
402 badgeBg: 'rgba(85,138,66,0.15)',
403 badgeColor: '#6BA656'
404 },
405 claude: {
406 badge: 'claude',
407 detail: "Claude's work",
408 badgeBg: 'rgba(217,119,87,0.12)',
409 badgeColor: '#D97757'
410 },
411 hook: {
412 badge: 'hook',
413 detail: 'Hook (automatic)',
414 badgeBg: 'rgba(184,134,11,0.15)',
415 badgeColor: '#CCA020'
416 },
417 compact: {
418 badge: 'compact',
419 detail: 'Compaction',
420 badgeBg: 'rgba(217,119,87,0.12)',
421 badgeColor: '#D97757'
422 },
423 sub: {
424 badge: 'subagent',
425 detail: "In subagent's context",
426 badgeBg: 'rgba(155,123,196,0.12)',
427 badgeColor: '#9B7BC4'
428 }
429 };
430 const LEGEND = [{
431 c: '#6B6964',
432 l: 'System'
433 }, {
434 c: '#6A9BCC',
435 l: 'CLAUDE.md'
436 }, {
437 c: '#E8A45C',
438 l: 'Memory'
439 }, {
440 c: '#D4A843',
441 l: 'Skills'
442 }, {
443 c: '#9B7BC4',
444 l: 'MCP'
445 }, {
446 c: '#4A9B8E',
447 l: 'Rules'
448 }, {
449 c: '#558A42',
450 l: 'You'
451 }, {
452 c: '#8A8880',
453 l: 'Files'
454 }, {
455 c: '#A09E96',
456 l: 'Output'
457 }, {
458 c: '#D97757',
459 l: 'Claude'
460 }, {
461 c: '#B8860B',
462 l: 'Hooks'
463 }];
464 const fmt = n => n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'K' : n + '';
465 const [time, setTime] = useState(0);
466 const [playing, setPlaying] = useState(false);
467 const [hovIdx, setHovIdx] = useState(null);
468 const [selIdx, setSelIdx] = useState(null);
469 const [hovCat, setHovCat] = useState(null);
470 const [gatesPassed, setGatesPassed] = useState(0);
471 const [mounted, setMounted] = useState(false);
472 const [hasInteracted, setHasInteracted] = useState(false);
473 const lastRef = useRef(null);
474 const scrollRef = useRef(null);
475 const detailRef = useRef(null);
476 useEffect(() => setMounted(true), []);
477 const activeGate = GATES.find((g, i) => i >= gatesPassed && time >= g.at && time < g.resumeTo);
478 useEffect(() => {
479 if (!playing) return;
480 let raf;
481 let stopped = false;
482 const tick = ts => {
483 if (stopped) return;
484 if (!lastRef.current) lastRef.current = ts;
485 const dt = (ts - lastRef.current) / 1000;
486 lastRef.current = ts;
487 setTime(prev => {
488 const next = prev + dt * 0.032;
489 const gate = GATES.find((g, i) => i >= gatesPassed && next >= g.at && prev < g.resumeTo);
490 if (gate) {
491 stopped = true;
492 setPlaying(false);
493 return gate.at;
494 }
495 if (next >= 1) {
496 stopped = true;
497 setPlaying(false);
498 return 1;
499 }
500 return next;
501 });
502 if (!stopped) raf = requestAnimationFrame(tick);
503 };
504 raf = requestAnimationFrame(tick);
505 return () => {
506 stopped = true;
507 cancelAnimationFrame(raf);
508 lastRef.current = null;
509 };
510 }, [playing, gatesPassed]);
511 const sendPrompt = () => {
512 if (!activeGate) return;
513 const isCompact = activeGate.kind === 'compact';
514 setGatesPassed(n => n + 1);
515 setTime(activeGate.resumeTo);
516 setSelIdx(null);
517 setHovIdx(null);
518 if (!isCompact) setPlaying(true);
519 };
520 const visibleCount = EVENTS.filter(e => e.t <= time).length;
521 const preCompactVisible = useMemo(() => EVENTS.slice(0, visibleCount), [EVENTS, visibleCount]);
522 const compactGateIdx = GATES.length - 1;
523 const isCompacted = gatesPassed > compactGateIdx && preCompactVisible.some(e => e.kind === 'compact');
524 const {visible, preCompactTotal} = useMemo(() => {
525 const nonCompact = preCompactVisible.filter(e => e.kind !== 'compact');
526 if (!isCompacted) {
527 return {
528 visible: preCompactVisible,
529 preCompactTotal: 0
530 };
531 }
532 {}
533 const autoLoads = nonCompact.filter(e => e.kind === 'auto' && e.t < STARTUP_END && !e.noSurviveCompact);
534 const summarized = nonCompact.filter(e => e.t >= STARTUP_END && e.kind !== 'sub');
535 const sumTokens = summarized.reduce((s, e) => s + e.tokens, 0);
536 const summaryBlock = {
537 t: STARTUP_END,
538 kind: 'compact',
539 label: 'Conversation summary',
540 tokens: Math.round(sumTokens * 0.12),
541 color: '#A09E96',
542 vis: 'hidden',
543 desc: `All ${summarized.length} conversation events condensed into one structured summary. The summary keeps: your requests and intent, key technical concepts, files examined or modified with important code snippets, errors and how they were fixed, pending tasks, and current work. It replaces the verbatim conversation: full tool outputs and intermediate reasoning are gone. Claude can still reference the work but won't have the exact code it read earlier.`,
544 link: '/en/how-claude-code-works#the-context-window'
545 };
546 return {
547 visible: [...autoLoads, summaryBlock],
548 preCompactTotal: nonCompact.reduce((s, e) => s + e.tokens, 0)
549 };
550 }, [preCompactVisible, isCompacted]);
551 const {blocks, totalTokens} = useMemo(() => {
552 const bl = visible.map((e, visIdx) => ({
553 ...e,
554 id: e.label + e.t,
555 visIdx
556 })).filter(e => e.tokens > 0 || e.label === 'Conversation summary');
557 return {
558 blocks: bl,
559 totalTokens: bl.reduce((s, b) => s + b.tokens, 0)
560 };
561 }, [visible]);
562 const subTotal = useMemo(() => visible.filter(e => e.kind === 'sub').reduce((s, e) => s + (e.subTokens || 0), 0), [visible]);
563 useEffect(() => {
564 if (!scrollRef.current) return;
565 if (isCompacted) scrollRef.current.scrollTo({
566 top: 0,
567 behavior: 'smooth'
568 }); else if (playing || activeGate) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
569 }, [visible.length, !!activeGate, isCompacted]);
570 const rootRef = useRef(null);
571 const keyStateRef = useRef({});
572 const [isFullscreen, setIsFullscreen] = useState(false);
573 keyStateRef.current = {
574 time,
575 activeGate,
576 sendPrompt,
577 hasInteracted
578 };
579 useEffect(() => {
580 const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);
581 document.addEventListener('fullscreenchange', onFsChange);
582 return () => document.removeEventListener('fullscreenchange', onFsChange);
583 }, []);
584 const toggleFullscreen = () => {
585 if (!rootRef.current) return;
586 if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {});
587 };
588 useEffect(() => {
589 const onKey = e => {
590 const tag = e.target.tagName;
591 if (tag === 'INPUT' || tag === 'BUTTON' || tag === 'TEXTAREA' || tag === 'SELECT' || e.target.isContentEditable) return;
592 if (!rootRef.current) return;
593 const rect = rootRef.current.getBoundingClientRect();
594 if (rect.width === 0 && rect.height === 0) return;
595 if (rect.bottom < 0 || rect.top > window.innerHeight) return;
596 if (e.code === 'Space') {
597 const {time: t, activeGate: g, sendPrompt: send, hasInteracted: hi} = keyStateRef.current;
598 if (!hi) return;
599 e.preventDefault();
600 if (t === 0) setPlaying(true); else if (g) send(); else if (t >= 1) {
601 setTime(0);
602 setGatesPassed(0);
603 setSelIdx(null);
604 setHovIdx(null);
605 setPlaying(true);
606 } else setPlaying(p => !p);
607 }
608 };
609 window.addEventListener('keydown', onKey);
610 return () => window.removeEventListener('keydown', onKey);
611 }, []);
612 const pct = totalTokens / MAX * 100;
613 const barColor = pct > 75 ? '#D97757' : pct > 50 ? '#B8860B' : '#558A42';
614 const activeIdx = selIdx !== null ? selIdx : hovIdx;
615 const hovEvent = activeIdx !== null ? visible[activeIdx] : null;
616 useEffect(() => {
617 if (detailRef.current) detailRef.current.scrollTop = 0;
618 }, [hovEvent]);
619 const focusT = hovEvent ? hovEvent.t : time;
620 const takeaway = isCompacted ? 'Compaction replaces the conversation with a structured summary. System prompt, CLAUDE.md, memory, and MCP tools reload automatically. The skill listing is the one exception. Only skills you actually invoked are preserved.' : focusT < STARTUP_END ? 'A lot loads before you type anything. CLAUDE.md, memory, skills, and MCP tools are all in context before your first prompt.' : focusT < 0.28 ? "Your prompt is tiny compared to what's already loaded. Most of Claude's context is project knowledge, not your words." : focusT < 0.50 ? 'Each file Claude reads grows the context. Path-scoped rules load automatically alongside matching files.' : focusT < 0.71 ? 'Hooks fire automatically on tool events. Output reaches Claude via additionalContext JSON. Exit code 2 surfaces stderr to Claude. Plain stdout on exit 0 goes to the debug log, not the transcript.' : focusT < 0.79 ? 'Follow-up questions keep building on the same context. Everything from earlier is still there.' : focusT < 0.87 ? "The subagent works in its own separate context window. None of its file reads touch yours. Only the final summary comes back." : focusT < 0.88 ? 'Bang commands run in your shell and prefix the output to your next message. Useful for grounding Claude in command results without it running them.' : focusT < 0.90 ? 'User-only skills stay out of context entirely until you invoke them. The skill index at startup only lists skills Claude can call on its own.' : '/compact summarizes the conversation to free space while keeping key information. In a real session, run it when context starts affecting performance or before a long new task.';
621 const terminalView = isCompacted ? 'A "Conversation compacted" message. The summarization happens silently.' : focusT < STARTUP_END ? 'The input box, waiting for your first message. Everything above loads silently before you type anything.' : focusT < 0.28 ? 'Your prompt. Claude hasn\'t started working yet.' : focusT < 0.52 ? 'Your prompt and "Reading files...". Rules show as one-line "Loaded" notices, not their content.' : focusT < 0.72 ? "Claude's response and file diffs. Hooks fire silently. Tool output like npm test shows as a brief summary, not the full content." : focusT < 0.79 ? 'Your follow-up prompt.' : focusT < 0.86 ? "A brief notice that a subagent is working, then its result. You don't see the subagent's individual file reads." : focusT < 0.90 ? "Claude's response, your git status output, and the commit-push skill running." : 'Your full conversation. /compact is available to run.';
622 const mono = 'var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace)';
623 const renderWithCode = s => s.split('`').map((part, i) => i % 2 === 1 ? <code key={i} style={{
624 fontFamily: mono,
625 fontSize: '0.92em',
626 background: 'var(--cw-track)',
627 padding: '1px 4px',
628 borderRadius: 3
629 }}>{part}</code> : part);
630 if (!mounted) return null;
631 return <>
632 <div className="cw-mobile-fallback">
633 This interactive timeline works best on a larger screen. See <a href="#what-the-timeline-shows" style={{
634 color: '#D97757'
635 }}>the written breakdown below</a> for the same concepts.
636 </div>
637 <div className="cw-root" ref={rootRef} onClickCapture={() => setHasInteracted(true)} style={isFullscreen ? {
638 height: '100vh',
639 borderRadius: 0,
640 display: 'flex',
641 flexDirection: 'column'
642 } : {}}>
643 <style>{`
644 .cw-root {
645 --cw-bg: #FAFAF8;
646 --cw-text: #1A1918;
647 --cw-text-2: #3D3C38;
648 --cw-text-3: #5E5D59;
649 --cw-text-dim: #6E6C64;
650 --cw-text-faint: #8A8880;
651 --cw-surface: rgba(0,0,0,0.025);
652 --cw-surface-2: rgba(0,0,0,0.04);
653 --cw-border: rgba(0,0,0,0.08);
654 --cw-track: rgba(0,0,0,0.04);
655 --cw-hover: rgba(0,0,0,0.04);
656 --cw-rail: rgba(0,0,0,0.08);
657 --cw-scrollbar: rgba(0,0,0,0.22);
658 background: var(--cw-bg);
659 border-radius: 12px;
660 overflow: hidden;
661 font-family: var(--font-sans, -apple-system, BlinkMacSystemFont, sans-serif);
662 color: var(--cw-text);
663 border: 1px solid var(--cw-border);
664 }
665 .dark .cw-root {
666 --cw-bg: #111110;
667 --cw-text: #E8E6DC;
668 --cw-text-2: #B8B6AE;
669 --cw-text-3: #9C9A92;
670 --cw-text-dim: #8A8880;
671 --cw-text-faint: #6E6C64;
672 --cw-surface: rgba(255,255,255,0.02);
673 --cw-surface-2: rgba(255,255,255,0.015);
674 --cw-border: rgba(255,255,255,0.06);
675 --cw-track: rgba(255,255,255,0.03);
676 --cw-hover: rgba(255,255,255,0.04);
677 --cw-rail: rgba(255,255,255,0.04);
678 --cw-scrollbar: rgba(255,255,255,0.18);
679 }
680 .cw-scroll::-webkit-scrollbar { width: 6px; }
681 .cw-scroll::-webkit-scrollbar-track { background: transparent; }
682 .cw-scroll::-webkit-scrollbar-thumb { background: var(--cw-scrollbar); border-radius: 3px; }
683 @keyframes cw-blink { 50% { opacity: 0; } }
684 @keyframes cw-fadein { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
685 .cw-compacted-row { animation: cw-fadein 0.3s ease-out backwards; }
686 .cw-mobile-fallback { display: none; padding: 14px 16px; border-radius: 8px; font-size: 14px; border: 1px solid rgba(0,0,0,0.1); background: rgba(0,0,0,0.03); }
687 .dark .cw-mobile-fallback { border-color: rgba(255,255,255,0.15); background: rgba(255,255,255,0.04); }
688 @media (max-width: 700px) {
689 .cw-root { display: none !important; }
690 .cw-mobile-fallback { display: block; }
691 }
692 `}</style>
10 693
11## Was die Zeitleiste zeigt694 {}
695 <div style={{
696 padding: '16px 20px 12px',
697 display: 'flex',
698 alignItems: 'flex-end',
699 gap: 24
700 }}>
701 <div style={{
702 flex: 1,
703 minWidth: 0
704 }}>
705 <div style={{
706 fontSize: 18,
707 fontWeight: 600,
708 letterSpacing: -0.3,
709 lineHeight: 1
710 }}>
711 Explore the context window
712 </div>
713 <div style={{
714 fontSize: 14,
715 color: 'var(--cw-text-dim)',
716 marginTop: 4
717 }}>
718 A simulated session showing what enters context and what it costs
719 </div>
720 </div>
721 <div style={{
722 textAlign: 'right',
723 flexShrink: 0
724 }}>
725 <div style={{
726 fontFamily: mono,
727 fontSize: 20,
728 fontWeight: 600,
729 color: barColor,
730 letterSpacing: -0.5,
731 lineHeight: 1
732 }}>
733 ~{fmt(totalTokens)}<span style={{
734 fontSize: 15,
735 fontWeight: 500,
736 marginLeft: 4
737 }}>tokens</span>
738 </div>
739 <div style={{
740 fontFamily: mono,
741 fontSize: 13,
742 color: 'var(--cw-text-dim)',
743 marginTop: 2
744 }} title="Token counts are illustrative. Actual values vary with your CLAUDE.md size, MCP servers, and file lengths.">
745 / {fmt(MAX)} · illustrative
746 </div>
747 </div>
748 </div>
749
750 {}
751 <div style={{
752 padding: '0 20px'
753 }}>
754 <div style={{
755 height: 4,
756 borderRadius: 2,
757 background: 'var(--cw-track)',
758 overflow: 'hidden',
759 marginBottom: 6
760 }}>
761 <div style={{
762 width: pct + '%',
763 height: '100%',
764 background: barColor,
765 transition: 'width 0.6s cubic-bezier(0.4, 0, 0.2, 1), background 0.3s'
766 }} />
767 </div>
768 <div style={{
769 height: 28,
770 borderRadius: 5,
771 background: 'var(--cw-track)',
772 border: '1px solid var(--cw-border)',
773 overflow: 'hidden',
774 display: 'flex'
775 }}>
776 {blocks.map((b, i) => {
777 const w = Math.max(b.tokens / MAX * 100, 0.15);
778 const isHov = b.visIdx === activeIdx;
779 const catMatch = hovCat && b.color === hovCat;
780 const dimmed = hovCat ? !catMatch : activeIdx !== null && !isHov;
781 return <div key={b.id} onMouseEnter={() => setHovIdx(b.visIdx)} onMouseLeave={() => setHovIdx(null)} onClick={() => setSelIdx(selIdx === b.visIdx ? null : b.visIdx)} style={{
782 width: w + '%',
783 height: '100%',
784 background: b.color,
785 opacity: isHov || catMatch ? 1 : dimmed ? 0.25 : 0.65,
786 borderRight: i < blocks.length - 1 ? '0.5px solid var(--cw-border)' : 'none',
787 transition: 'opacity 0.15s',
788 cursor: 'pointer'
789 }} />;
790 })}
791 </div>
792 <div style={{
793 display: 'flex',
794 gap: 12,
795 marginTop: 6,
796 flexWrap: 'wrap',
797 justifyContent: 'space-between'
798 }}>
799 <div style={{
800 display: 'flex',
801 gap: 12,
802 flexWrap: 'wrap'
803 }}>
804 {LEGEND.map(x => {
805 const active = hovCat === x.c;
806 return <div key={x.l} onMouseEnter={() => setHovCat(x.c)} onMouseLeave={() => setHovCat(null)} style={{
807 display: 'flex',
808 alignItems: 'center',
809 gap: 4,
810 padding: '2px 6px',
811 borderRadius: 4,
812 cursor: 'pointer',
813 background: active ? 'var(--cw-hover)' : 'transparent',
814 transition: 'background 0.1s'
815 }}>
816 <div style={{
817 width: 6,
818 height: 6,
819 borderRadius: 1.5,
820 background: x.c,
821 opacity: active ? 1 : 0.7
822 }} />
823 <span style={{
824 fontSize: 12,
825 color: active ? 'var(--cw-text)' : 'var(--cw-text-dim)'
826 }}>{x.l}</span>
827 </div>;
828 })}
829 </div>
830 <div style={{
831 display: 'flex',
832 gap: 6,
833 alignItems: 'center',
834 fontSize: 12,
835 color: 'var(--cw-text-dim)'
836 }}>
837 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#558A42" strokeWidth="2.5">
838 <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" /><circle cx="12" cy="12" r="3" />
839 </svg>
840 <span>= appears in your terminal</span>
841 </div>
842 </div>
843 </div>
844
845 {}
846 <div style={{
847 display: 'flex',
848 padding: '14px 20px 0',
849 gap: 16,
850 height: isFullscreen ? 'calc(100vh - 240px)' : 420
851 }}>
852
853 {}
854 <div ref={scrollRef} className="cw-scroll" style={{
855 flex: 1,
856 minWidth: 0,
857 overflowY: 'auto',
858 paddingRight: 8,
859 scrollBehavior: 'smooth'
860 }}>
861 {visible.length === 0 && !playing && <div style={{
862 height: '100%',
863 display: 'flex',
864 flexDirection: 'column',
865 alignItems: 'center',
866 justifyContent: 'center',
867 gap: 16
868 }}>
869 <div style={{
870 fontFamily: mono,
871 fontSize: 16,
872 color: 'var(--cw-text-dim)',
873 display: 'flex',
874 alignItems: 'center',
875 gap: 8
876 }}>
877 <span style={{
878 color: 'var(--cw-text-faint)'
879 }}>$</span>
880 <span>claude</span>
881 <span style={{
882 display: 'inline-block',
883 width: 8,
884 height: 16,
885 background: 'var(--cw-text-dim)',
886 opacity: 0.5,
887 animation: 'cw-blink 1s step-end infinite'
888 }} />
889 </div>
890 <button onClick={() => setPlaying(true)} style={{
891 padding: '10px 20px',
892 borderRadius: 8,
893 border: '1px solid rgba(217,119,87,0.3)',
894 background: 'rgba(217,119,87,0.08)',
895 color: '#D97757',
896 fontSize: 15,
897 fontWeight: 600,
898 cursor: 'pointer',
899 display: 'flex',
900 alignItems: 'center',
901 gap: 8
902 }}>
903 <span>▶</span>
904 <span>Start session</span>
905 </button>
906 <div style={{
907 fontSize: 13,
908 color: 'var(--cw-text-faint)',
909 maxWidth: 280,
910 textAlign: 'center',
911 lineHeight: 1.5
912 }}>
913 Watch what loads into context, from the moment you run <code style={{
914 fontFamily: mono
915 }}>claude</code> through a full conversation.
916 </div>
917 </div>}
918 {isCompacted && <div style={{
919 marginBottom: 10,
920 padding: '10px 12px',
921 borderRadius: 6,
922 background: 'rgba(217,119,87,0.05)',
923 border: '1px solid rgba(217,119,87,0.15)'
924 }}>
925 <div style={{
926 fontSize: 13,
927 fontWeight: 600,
928 color: '#D97757',
929 marginBottom: 3
930 }}>
931 After /compact
932 </div>
933 <div style={{
934 fontSize: 13,
935 color: 'var(--cw-text-3)',
936 lineHeight: 1.5,
937 fontFamily: mono
938 }}>
939 {fmt(preCompactTotal)} → {fmt(totalTokens)} tokens · freed {fmt(preCompactTotal - totalTokens)}
940 </div>
941 <div style={{
942 fontSize: 13,
943 color: 'var(--cw-text-dim)',
944 lineHeight: 1.5,
945 marginTop: 4
946 }}>
947 This is what's left in context: startup content, which lives outside the message history and reloads after compaction, plus a structured summary of the entire conversation. Skill descriptions don't reload.
948 </div>
949 </div>}
950 {time > 0 && visible.length > 0 && <div style={{
951 fontSize: 12,
952 fontWeight: 700,
953 color: 'var(--cw-text-faint)',
954 textTransform: 'uppercase',
955 letterSpacing: 0.6,
956 marginBottom: 6,
957 paddingLeft: 28
958 }}>
959 {isCompacted ? 'Reloaded after compact' : 'Before you type anything'}
960 </div>}
961
962 {time > 0 && visible.map((evt, i) => {
963 const meta = KIND_META[evt.kind];
964 const isHov = hovIdx === i;
965 const prevKind = i > 0 ? visible[i - 1].kind : null;
966 const isSub = evt.kind === 'sub';
967 const enteringSubagent = isSub && prevKind !== 'sub';
968 const leavingSubagent = prevKind === 'sub' && !isSub;
969 let showPhase = null;
970 if (evt.kind === 'user' && prevKind !== 'user') showPhase = 'You'; else if (evt.kind === 'claude' && prevKind === 'user') showPhase = 'Claude works'; else if (evt.label === 'Conversation summary') showPhase = 'Summarized by /compact';
971 const isNewRow = isCompacted && !(evt.kind === 'auto' && evt.t < STARTUP_END);
972 return <div key={evt.label + evt.t} className={isNewRow ? 'cw-compacted-row' : ''} style={isNewRow ? {
973 animationDelay: `${i * 60}ms`
974 } : {}}>
975 {showPhase && <div style={{
976 fontSize: 12,
977 fontWeight: 700,
978 color: 'var(--cw-text-faint)',
979 textTransform: 'uppercase',
980 letterSpacing: 0.6,
981 marginTop: 14,
982 marginBottom: 6,
983 paddingLeft: 28
984 }}>
985 {showPhase}
986 </div>}
987 {enteringSubagent && <div style={{
988 marginLeft: 28,
989 marginTop: 6,
990 marginBottom: 2,
991 paddingLeft: 10,
992 borderLeft: '2px solid rgba(155,123,196,0.4)',
993 fontSize: 12,
994 fontWeight: 600,
995 color: '#9B7BC4',
996 textTransform: 'uppercase',
997 letterSpacing: 0.5
998 }}>
999 Subagent's separate context window
1000 </div>}
1001 {leavingSubagent && <div style={{
1002 marginLeft: 28,
1003 marginBottom: 6,
1004 paddingLeft: 10,
1005 paddingBottom: 6,
1006 borderLeft: '2px solid rgba(155,123,196,0.4)',
1007 fontSize: 12,
1008 color: 'var(--cw-text-dim)',
1009 fontFamily: mono
1010 }}>
1011 ↓ {fmt(subTotal)} tokens stayed in subagent's context · only the summary returns
1012 </div>}
1013 <div onMouseEnter={() => setHovIdx(i)} onMouseLeave={() => setHovIdx(null)} onClick={() => setSelIdx(selIdx === i ? null : i)} style={{
1014 display: 'flex',
1015 alignItems: 'flex-start',
1016 borderRadius: 6,
1017 cursor: 'pointer',
1018 background: selIdx === i || isHov ? 'var(--cw-hover)' : 'transparent',
1019 outline: selIdx === i ? '1px solid rgba(217,119,87,0.4)' : 'none',
1020 opacity: hovCat && evt.color !== hovCat ? 0.35 : 1,
1021 transition: 'background 0.1s, opacity 0.15s',
1022 marginLeft: isSub ? 28 : 0,
1023 paddingLeft: isSub ? 10 : 0,
1024 borderLeft: isSub ? '2px solid rgba(155,123,196,0.4)' : 'none'
1025 }}>
1026 <div style={{
1027 width: 28,
1028 display: 'flex',
1029 flexDirection: 'column',
1030 alignItems: 'center',
1031 paddingTop: 8,
1032 flexShrink: 0
1033 }}>
1034 <div style={{
1035 width: evt.kind === 'user' || evt.kind === 'compact' ? 10 : 7,
1036 height: evt.kind === 'user' || evt.kind === 'compact' ? 10 : 7,
1037 borderRadius: '50%',
1038 background: evt.color,
1039 opacity: isHov ? 1 : 0.6,
1040 transition: 'opacity 0.15s',
1041 boxShadow: isHov ? `0 0 8px ${evt.color}40` : 'none'
1042 }} />
1043 {i < visible.length - 1 && <div style={{
1044 width: 1.5,
1045 flex: 1,
1046 background: 'var(--cw-rail)',
1047 marginTop: 2,
1048 minHeight: 6
1049 }} />}
1050 </div>
1051 <div style={{
1052 flex: 1,
1053 minWidth: 0,
1054 padding: '5px 10px 5px 4px',
1055 display: 'flex',
1056 alignItems: 'center',
1057 gap: 8
1058 }}>
1059 <span style={{
1060 fontSize: 12,
1061 fontWeight: 600,
1062 padding: '1px 5px',
1063 borderRadius: 3,
1064 background: meta.badgeBg,
1065 color: meta.badgeColor,
1066 flexShrink: 0,
1067 fontFamily: mono
1068 }}>
1069 {meta.badge}
1070 </span>
1071 <span style={{
1072 fontSize: 15,
1073 fontFamily: mono,
1074 color: isHov ? 'var(--cw-text)' : evt.kind === 'user' ? '#558A42' : evt.kind === 'auto' ? 'var(--cw-text-dim)' : 'var(--cw-text-2)',
1075 flex: 1,
1076 minWidth: 0,
1077 overflow: 'hidden',
1078 textOverflow: 'ellipsis',
1079 whiteSpace: 'nowrap',
1080 fontWeight: evt.kind === 'user' ? 550 : 400
1081 }}>
1082 {evt.label}
1083 </span>
1084 {evt.tokens > 0 && <span style={{
1085 fontSize: 12,
1086 fontFamily: mono,
1087 color: 'var(--cw-text-faint)',
1088 flexShrink: 0
1089 }}>
1090 +{fmt(evt.tokens)}
1091 </span>}
1092 {evt.subTokens > 0 && <span style={{
1093 fontSize: 12,
1094 fontFamily: mono,
1095 color: '#9B7BC4',
1096 flexShrink: 0,
1097 opacity: 0.6
1098 }}>
1099 +{fmt(evt.subTokens)}
1100 </span>}
1101 {evt.tokens > 0 && <div style={{
1102 width: 50,
1103 height: 5,
1104 borderRadius: 2,
1105 background: 'var(--cw-track)',
1106 flexShrink: 0,
1107 overflow: 'hidden'
1108 }}>
1109 <div style={{
1110 width: Math.min(evt.tokens / 5000 * 100, 100) + '%',
1111 height: '100%',
1112 background: evt.color,
1113 opacity: isHov ? 0.8 : 0.4,
1114 transition: 'opacity 0.15s'
1115 }} />
1116 </div>}
1117 <span style={{
1118 width: 14,
1119 flexShrink: 0,
1120 display: 'flex',
1121 justifyContent: 'center'
1122 }} title={VIS_META[evt.vis].label}>
1123 {evt.vis !== 'hidden' && <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke={evt.vis === 'full' ? '#558A42' : 'currentColor'} style={{
1124 color: 'var(--cw-text-faint)',
1125 opacity: evt.vis === 'full' ? 1 : 0.5
1126 }} strokeWidth="2">
1127 <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" /><circle cx="12" cy="12" r="3" />
1128 </svg>}
1129 </span>
1130 </div>
1131 </div>
1132 </div>;
1133 })}
1134
1135 {activeGate && (activeGate.kind === 'prompt' || activeGate.kind === 'bang' || activeGate.kind === 'slash') && <div style={{
1136 paddingLeft: 28,
1137 marginTop: 12,
1138 paddingRight: 8
1139 }}>
1140 <div style={{
1141 fontSize: 11,
1142 fontWeight: 600,
1143 color: '#6BA656',
1144 fontFamily: mono,
1145 textTransform: 'uppercase',
1146 letterSpacing: 0.5,
1147 marginBottom: 4,
1148 paddingLeft: 2
1149 }}>
1150 You type in your terminal
1151 </div>
1152 <div style={{
1153 display: 'flex',
1154 alignItems: 'flex-start',
1155 gap: 8,
1156 padding: '10px 12px',
1157 borderRadius: 6,
1158 background: 'rgba(85,138,66,0.06)',
1159 border: '1px solid rgba(85,138,66,0.2)'
1160 }}>
1161 <span style={{
1162 color: '#558A42',
1163 fontSize: 15,
1164 fontFamily: mono,
1165 flexShrink: 0
1166 }}>❯</span>
1167 <span style={{
1168 fontSize: 15,
1169 fontFamily: mono,
1170 color: 'var(--cw-text-2)',
1171 flex: 1,
1172 lineHeight: 1.5
1173 }}>
1174 {activeGate.text}
1175 <span style={{
1176 display: 'inline-block',
1177 width: 7,
1178 height: 13,
1179 marginLeft: 2,
1180 background: '#558A42',
1181 opacity: 0.5,
1182 verticalAlign: 'middle',
1183 animation: 'cw-blink 1s step-end infinite'
1184 }} />
1185 </span>
1186 <button onClick={sendPrompt} style={{
1187 padding: '5px 12px',
1188 borderRadius: 5,
1189 border: 'none',
1190 background: '#558A42',
1191 color: '#fff',
1192 fontSize: 13,
1193 fontWeight: 600,
1194 cursor: 'pointer',
1195 flexShrink: 0
1196 }}>
1197 {activeGate.kind === 'prompt' ? 'Send ↵' : 'Run ↵'}
1198 </button>
1199 </div>
1200 </div>}
1201 {activeGate && activeGate.kind === 'compact' && <div style={{
1202 paddingLeft: 28,
1203 marginTop: 12,
1204 paddingRight: 8
1205 }}>
1206 <div style={{
1207 padding: '12px 14px',
1208 borderRadius: 6,
1209 background: 'rgba(217,119,87,0.06)',
1210 border: '1px solid rgba(217,119,87,0.25)'
1211 }}>
1212 <div style={{
1213 fontSize: 13,
1214 color: 'var(--cw-text-3)',
1215 marginBottom: 8,
1216 lineHeight: 1.5
1217 }}>
1218 Context is at <span style={{
1219 fontFamily: mono,
1220 fontWeight: 600,
1221 color: barColor
1222 }}>{fmt(totalTokens)} tokens</span>.
1223 Run <code style={{
1224 fontFamily: mono,
1225 background: 'var(--cw-track)',
1226 padding: '1px 4px',
1227 borderRadius: 3
1228 }}>/compact</code> to
1229 summarize older exchanges and free space for more work.
1230 </div>
1231 <div style={{
1232 display: 'flex',
1233 alignItems: 'center',
1234 gap: 8
1235 }}>
1236 <span style={{
1237 color: '#D97757',
1238 fontSize: 15,
1239 fontFamily: mono
1240 }}>❯</span>
1241 <span style={{
1242 fontSize: 15,
1243 fontFamily: mono,
1244 color: 'var(--cw-text-2)',
1245 flex: 1
1246 }}>
1247 {activeGate.text}
1248 </span>
1249 <button onClick={sendPrompt} style={{
1250 padding: '5px 12px',
1251 borderRadius: 5,
1252 border: 'none',
1253 background: '#D97757',
1254 color: '#fff',
1255 fontSize: 13,
1256 fontWeight: 600,
1257 cursor: 'pointer',
1258 flexShrink: 0
1259 }}>
1260 Run ↵
1261 </button>
1262 </div>
1263 </div>
1264 </div>}
1265 </div>
1266
1267 {}
1268 <div style={{
1269 width: 300,
1270 flexShrink: 0,
1271 display: 'flex',
1272 flexDirection: 'column'
1273 }}>
1274 <div ref={detailRef} className="cw-scroll" style={{
1275 padding: '14px 16px',
1276 borderRadius: 10,
1277 background: 'var(--cw-surface)',
1278 border: '1px solid var(--cw-border)',
1279 flex: 1,
1280 minHeight: 0,
1281 overflowY: 'auto',
1282 display: 'flex',
1283 flexDirection: 'column',
1284 gap: 10
1285 }}>
1286 {hovEvent ? <div>
1287 <div style={{
1288 display: 'flex',
1289 alignItems: 'center',
1290 gap: 8,
1291 marginBottom: 8
1292 }}>
1293 <div style={{
1294 width: 10,
1295 height: 10,
1296 borderRadius: 3,
1297 background: hovEvent.color,
1298 opacity: 0.8
1299 }} />
1300 <span style={{
1301 fontSize: 16,
1302 fontWeight: 600
1303 }}>{hovEvent.label}</span>
1304 </div>
1305 <div style={{
1306 display: 'flex',
1307 width: 'fit-content',
1308 padding: '3px 8px',
1309 borderRadius: 4,
1310 marginBottom: 8,
1311 background: KIND_META[hovEvent.kind].badgeBg
1312 }}>
1313 <span style={{
1314 fontSize: 12,
1315 fontWeight: 600,
1316 color: KIND_META[hovEvent.kind].badgeColor
1317 }}>
1318 {KIND_META[hovEvent.kind].detail}
1319 </span>
1320 </div>
1321 {hovEvent.tokens > 0 && <div style={{
1322 fontSize: 14,
1323 fontFamily: mono,
1324 color: 'var(--cw-text-dim)',
1325 marginBottom: 6
1326 }}>
1327 {fmt(hovEvent.tokens)} tokens
1328 </div>}
1329 {hovEvent.subTokens > 0 && <div style={{
1330 fontSize: 14,
1331 fontFamily: mono,
1332 color: '#9B7BC4',
1333 marginBottom: 6
1334 }}>
1335 {fmt(hovEvent.subTokens)} tokens in the subagent's context
1336 </div>}
1337 <p style={{
1338 fontSize: 15,
1339 color: 'var(--cw-text-3)',
1340 lineHeight: 1.55,
1341 margin: 0
1342 }}>
1343 {renderWithCode(hovEvent.desc)}
1344 </p>
1345 <div style={{
1346 marginTop: 10,
1347 padding: '8px 10px',
1348 borderRadius: 6,
1349 background: hovEvent.vis === 'full' ? 'rgba(85,138,66,0.08)' : 'var(--cw-surface-2)',
1350 border: '1px solid ' + (hovEvent.vis === 'full' ? 'rgba(85,138,66,0.2)' : 'var(--cw-border)')
1351 }}>
1352 <div style={{
1353 display: 'flex',
1354 alignItems: 'center',
1355 gap: 6,
1356 marginBottom: 3
1357 }}>
1358 <span style={{
1359 fontSize: 13,
1360 color: hovEvent.vis === 'full' ? '#558A42' : 'var(--cw-text-dim)'
1361 }}>
1362 {hovEvent.vis === 'full' ? '●' : hovEvent.vis === 'brief' ? '◐' : '○'}
1363 </span>
1364 <span style={{
1365 fontSize: 12,
1366 fontWeight: 600,
1367 color: 'var(--cw-text-2)'
1368 }}>
1369 {VIS_META[hovEvent.vis].label}
1370 </span>
1371 </div>
1372 <div style={{
1373 fontSize: 13,
1374 color: 'var(--cw-text-dim)',
1375 lineHeight: 1.4
1376 }}>
1377 {VIS_META[hovEvent.vis].sub}
1378 </div>
1379 </div>
1380 {hovEvent.tip && <div style={{
1381 marginTop: 10,
1382 padding: '8px 10px',
1383 borderRadius: 6,
1384 background: 'rgba(85,138,66,0.06)',
1385 border: '1px solid rgba(85,138,66,0.15)'
1386 }}>
1387 <div style={{
1388 fontSize: 12,
1389 fontWeight: 600,
1390 color: '#558A42',
1391 marginBottom: 3,
1392 display: 'flex',
1393 alignItems: 'center',
1394 gap: 4
1395 }}>
1396 <span>💡</span> Save context
1397 </div>
1398 <div style={{
1399 fontSize: 13,
1400 color: 'var(--cw-text-3)',
1401 lineHeight: 1.5
1402 }}>
1403 {renderWithCode(hovEvent.tip)}
1404 </div>
1405 </div>}
1406 {hovEvent.link && <a href={hovEvent.link} style={{
1407 display: 'inline-block',
1408 marginTop: 10,
1409 fontSize: 13,
1410 color: '#D97757',
1411 textDecoration: 'none',
1412 borderBottom: '1px solid rgba(217,119,87,0.3)'
1413 }}>
1414 Learn more →
1415 </a>}
1416 </div> : <div style={{
1417 display: 'flex',
1418 flexDirection: 'column',
1419 alignItems: 'center',
1420 textAlign: 'center',
1421 gap: 4,
1422 padding: '12px 0 4px'
1423 }}>
1424 <div style={{
1425 fontSize: 22,
1426 opacity: 0.2
1427 }}>👁</div>
1428 <div style={{
1429 fontSize: 14,
1430 fontWeight: 500,
1431 color: 'var(--cw-text-dim)'
1432 }}>Hover or click any event</div>
1433 <div style={{
1434 fontSize: 12,
1435 color: 'var(--cw-text-faint)',
1436 lineHeight: 1.4,
1437 maxWidth: 200
1438 }}>
1439 Hover to preview. Click to pin so you can scroll.
1440 </div>
1441 </div>}
1442
1443 <div style={{
1444 padding: '10px 12px',
1445 borderRadius: 8,
1446 background: 'rgba(217,119,87,0.05)',
1447 border: '1px solid rgba(217,119,87,0.12)'
1448 }}>
1449 <div style={{
1450 fontSize: 11,
1451 fontWeight: 700,
1452 color: '#D97757',
1453 textTransform: 'uppercase',
1454 letterSpacing: 0.5,
1455 marginBottom: 3
1456 }}>
1457 Key takeaway
1458 </div>
1459 <div style={{
1460 fontSize: 13,
1461 color: 'var(--cw-text-3)',
1462 lineHeight: 1.5
1463 }}>
1464 {takeaway}
1465 </div>
1466 </div>
1467
1468 <div style={{
1469 padding: '10px 12px',
1470 borderRadius: 8,
1471 background: 'var(--cw-surface-2)',
1472 border: '1px solid var(--cw-border)'
1473 }}>
1474 <div style={{
1475 fontSize: 11,
1476 fontWeight: 700,
1477 color: 'var(--cw-text-dim)',
1478 textTransform: 'uppercase',
1479 letterSpacing: 0.5,
1480 marginBottom: 3
1481 }}>
1482 In your terminal you see
1483 </div>
1484 <div style={{
1485 fontSize: 13,
1486 color: 'var(--cw-text-3)',
1487 lineHeight: 1.5
1488 }}>
1489 {terminalView}
1490 </div>
1491 </div>
1492 </div>
1493 </div>
1494 </div>
1495
1496 {}
1497 <div style={{
1498 padding: '10px 20px 14px',
1499 display: 'flex',
1500 alignItems: 'center',
1501 gap: 10
1502 }}>
1503 <button aria-label={time >= 1 ? 'Restart' : activeGate ? 'Continue' : playing ? 'Pause' : 'Play'} onClick={() => {
1504 if (time >= 1) {
1505 setTime(0);
1506 setGatesPassed(0);
1507 setSelIdx(null);
1508 setHovIdx(null);
1509 setPlaying(true);
1510 } else if (activeGate) sendPrompt(); else setPlaying(!playing);
1511 }} style={{
1512 width: 30,
1513 height: 30,
1514 borderRadius: 6,
1515 border: 'none',
1516 background: 'rgba(217,119,87,0.1)',
1517 color: '#D97757',
1518 cursor: 'pointer',
1519 fontSize: 15,
1520 fontWeight: 700,
1521 display: 'flex',
1522 alignItems: 'center',
1523 justifyContent: 'center'
1524 }}>
1525 {time >= 1 ? '↺' : playing ? '⏸' : '▶'}
1526 </button>
1527 <div style={{
1528 flex: 1,
1529 height: 3,
1530 borderRadius: 2,
1531 background: 'var(--cw-track)',
1532 overflow: 'hidden'
1533 }}>
1534 <div style={{
1535 width: time * 100 + '%',
1536 height: '100%',
1537 background: '#D97757',
1538 transition: 'width 0.1s linear'
1539 }} />
1540 </div>
1541 <span style={{
1542 fontSize: 12,
1543 fontFamily: mono,
1544 color: 'var(--cw-text-faint)',
1545 minWidth: 30
1546 }}>
1547 {Math.round(time * 100)}%
1548 </span>
1549 <button onClick={toggleFullscreen} aria-label={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'} style={{
1550 width: 28,
1551 height: 28,
1552 borderRadius: 6,
1553 border: '1px solid var(--cw-border)',
1554 background: 'var(--cw-surface)',
1555 color: 'var(--cw-text-dim)',
1556 cursor: 'pointer',
1557 fontSize: 15,
1558 flexShrink: 0,
1559 marginLeft: 4,
1560 display: 'flex',
1561 alignItems: 'center',
1562 justifyContent: 'center'
1563 }}>
1564 {isFullscreen ? '⤡' : '⛶'}
1565 </button>
1566 </div>
1567 </div>
1568 </>;
1569};
1570
1571Das Kontextfenster von Claude Code enthält alles, was Claude über Ihre Sitzung weiß: Ihre Anweisungen, die Dateien, die es liest, seine eigenen Antworten und Inhalte, die nie in Ihrem Terminal erscheinen. Die folgende Zeitleiste zeigt eine vollständige Sitzung vom Start bis zur Komprimierung: was geladen wird, bevor Sie etwas eingeben, was jeder Dateilesevorgang, jede Regel und jeder Hook hinzufügt, während Claude arbeitet, und wie ein Subagent große Lesevorgänge aus Ihrem Kontext heraushält. Siehe [die schriftliche Aufschlüsselung](#what-the-timeline-shows) für denselben Inhalt als Liste.
1572
1573<ContextWindow />
1574
1575<h2 id="what-the-timeline-shows">
1576 Was die Zeitleiste zeigt
1577</h2>
12 1578
13Die Sitzung durchläuft einen realistischen Ablauf mit repräsentativen Token-Zählungen:1579Die Sitzung durchläuft einen realistischen Ablauf mit repräsentativen Token-Zählungen:
14 1580
17* **Die Folgeeingabeaufforderung**: Ein [Subagent](/de/sub-agents) verarbeitet die Recherche in seinem eigenen separaten Kontextfenster, sodass die großen Dateilesevorgang außerhalb des Ihren bleiben. Nur die Zusammenfassung und ein kleiner Metadaten-Trailer kommen zurück.1583* **Die Folgeeingabeaufforderung**: Ein [Subagent](/de/sub-agents) verarbeitet die Recherche in seinem eigenen separaten Kontextfenster, sodass die großen Dateilesevorgang außerhalb des Ihren bleiben. Nur die Zusammenfassung und ein kleiner Metadaten-Trailer kommen zurück.
18* **Am Ende**: `/compact` ersetzt die Konversation durch eine strukturierte Zusammenfassung. Der meiste Startuinhalt wird automatisch neu geladen; die folgende Tabelle zeigt, was mit jedem Mechanismus geschieht.1584* **Am Ende**: `/compact` ersetzt die Konversation durch eine strukturierte Zusammenfassung. Der meiste Startuinhalt wird automatisch neu geladen; die folgende Tabelle zeigt, was mit jedem Mechanismus geschieht.
19 1585
20## Was die Komprimierung übersteht1586<h2 id="what-survives-compaction">
1587 Was die Komprimierung übersteht
1588</h2>
21 1589
22Wenn eine lange Sitzung komprimiert wird, fasst Claude Code die Konversationshistorie zusammen, um in das Kontextfenster zu passen. Was mit Ihren Anweisungen geschieht, hängt davon ab, wie sie geladen wurden:1590Wenn eine lange Sitzung komprimiert wird, fasst Claude Code die Konversationshistorie zusammen, um in das Kontextfenster zu passen. Was mit Ihren Anweisungen geschieht, hängt davon ab, wie sie geladen wurden:
23 1591
35 1603
36Skill-Texte werden nach der Komprimierung neu eingefügt, aber große Skills werden auf die Pro-Skill-Grenze gekürzt, und die ältesten aufgerufenen Skills werden gelöscht, sobald das Gesamtbudget überschritten wird. Die Kürzung behält den Anfang der Datei bei, daher sollten Sie die wichtigsten Anweisungen oben in `SKILL.md` platzieren.1604Skill-Texte werden nach der Komprimierung neu eingefügt, aber große Skills werden auf die Pro-Skill-Grenze gekürzt, und die ältesten aufgerufenen Skills werden gelöscht, sobald das Gesamtbudget überschritten wird. Die Kürzung behält den Anfang der Datei bei, daher sollten Sie die wichtigsten Anweisungen oben in `SKILL.md` platzieren.
37 1605
38## Überprüfen Sie Ihre eigene Sitzung1606<h2 id="when-your-context-fills-up">
1607 Wenn sich Ihr Kontext füllt
1608</h2>
1609
1610Claude Code komprimiert automatisch, wenn Sie sich dem Limit nähern, sodass ein volles Kontextfenster Ihre Sitzung nicht beendet. Der automatische Durchgang funktioniert genauso wie der `/compact`-Schritt in der Zeitleiste. Siehe [Wenn sich der Kontext füllt](/de/how-claude-code-works#when-context-fills-up) für das, was er bewahrt.
1611
1612Sie können auch handeln, bevor der automatische Durchgang ausgeführt wird:
1613
1614* **Mit Fokus komprimieren**: Führen Sie `/compact` mit Anweisungen aus, wie `/compact focus on the auth bug fix`, bevor Sie eine lange neue Aufgabe starten. Die Zusammenfassung behält das, was Sie wählen, anstelle dessen, was der automatische Durchgang als wichtig erachtet.
1615* **Zwischen Aufgaben löschen**: Führen Sie `/clear` aus, wenn Sie zu nicht verwandter Arbeit wechseln. Alte Konversationen verdrängen die Dateien, die Sie als nächstes benötigen, und kosten Token bei jeder Nachricht.
1616* **Große Lesevorgänge delegieren**: Senden Sie Recherche an einen [Subagent](/de/sub-agents), sodass die Dateiinhalte in seinem Kontextfenster bleiben, nicht in Ihrem.
1617
1618Wenn Sie ein größeres Fenster benötigen, anstatt ein kleineres Gespräch zu führen, unterstützen Fable 5, Opus 4.6 und später sowie Sonnet 4.6 ein Kontextfenster mit 1 Million Token. Siehe [Erweiterter Kontext](/de/model-config#extended-context) für die Verfügbarkeit nach Plan und wie Sie eine `[1m]` Modellvariante auswählen. Die Komprimierung funktioniert auf die gleiche Weise bei der größeren Grenze.
1619
1620<h2 id="check-your-own-session">
1621 Überprüfen Sie Ihre eigene Sitzung
1622</h2>
39 1623
40Die Visualisierung verwendet repräsentative Zahlen. Um Ihre tatsächliche Kontextnutzung zu einem beliebigen Zeitpunkt zu sehen, führen Sie `/context` aus, um eine Live-Aufschlüsselung nach Kategorie mit Optimierungsvorschlägen zu erhalten. Führen Sie `/memory` aus, um zu überprüfen, welche CLAUDE.md- und automatische Gedächtnis-Dateien beim Start geladen wurden.1624Die Visualisierung verwendet repräsentative Zahlen. Um Ihre tatsächliche Kontextnutzung zu einem beliebigen Zeitpunkt zu sehen, führen Sie `/context` aus, um eine Live-Aufschlüsselung nach Kategorie mit Optimierungsvorschlägen zu erhalten. Führen Sie `/memory` aus, um zu überprüfen, welche CLAUDE.md- und automatische Gedächtnis-Dateien beim Start geladen wurden.
41 1625
42## Verwandte Ressourcen1626<h2 id="related-resources">
1627 Verwandte Ressourcen
1628</h2>
43 1629
44Für eine tiefere Abdeckung der in der Zeitleiste gezeigten Funktionen siehe diese Seiten:1630Für eine tiefere Abdeckung der in der Zeitleiste gezeigten Funktionen siehe diese Seiten:
45 1631