Jak je postavený Claude Code – architektura CLI s 1 884 soubory

Claude Code od Anthropicu vypadá jako jednoduchá terminálová utilita. Napíšete dotaz, dostanete odpověď, Claude upraví soubor. Pod kapotou ale běží aplikace o 29 MB TypeScriptového kódu, kde každý nástroj je samostatný modul, systémový prompt se skládá z patnácti sekcí a polovina funkcí se načítá až ve chvíli, kdy je skutečně potřeba.

Tento článek rozebírá, jak je Claude Code postaven – od adresářové struktury přes plugin systém až po mechanismy, které zajišťují, že se celý kolos spustí za méně než sekundu.


Anatomie projektu

Zdrojový kód žije v adresáři src/ a dělí se do jasně oddělených vrstev:

Vrstva Adresář Odpovědnost
Vstupní body entrypoints/ CLI, SDK, server mód
Jádro query.ts, QueryEngine.ts, main.tsx Hlavní smyčka, komunikace s API
Nástroje tools/ (40+ podadresářů) Každý nástroj samostatný modul
Služby services/ (20+ podadresářů) MCP, analytics, API, rate limits, hlas
Konfigurace constants/ Systémový prompt, výchozí hodnoty
Utilities utils/ Sanitizace, Git, oprávnění, cache
UI components/, screens/, ink/ Terminálové rozhraní (React Ink)
Stav state/, bootstrap/ Globální stav aplikace

Hlavní soubor main.tsx má 803 KB. Není to monolitický blok – je to vstupní bod, který orchestruje celý životní cyklus aplikace: bootstrap, migrace, inicializace služeb, vykreslení UI a hlavní smyčku.


Systém nástrojů – kontrakt s 20 metodami

Každý nástroj v Claude Code implementuje rozhraní Tool, definované v souboru Tool.ts (793 řádků). Toto rozhraní je zároveň kontraktem – jakýsi „stavební předpis“, který musí každý nástroj splnit.

Klíčové metody kontraktu:

call() – hlavní logika nástroje. Přijímá typované vstupy (Zod schéma), kontext relace a callback pro hlášení průběhu. Vrací strukturovaný výsledek.

checkPermissions() – rozhoduje, zda nástroj smí být spuštěn s danými vstupy v aktuálním kontextu. Tato metoda je povinná pro všechny nástroje bez výjimky.

isEnabled() – dynamická kontrola, zda má nástroj vůbec existovat v aktuálním prostředí. Například PowerShell nástroj se aktivuje pouze na Windows.

isReadOnly() – označuje, zda operace pouze čte data. Čtecí operace mají volnější pravidla oprávnění.

isDestructive() – indikátor nevratných operací (mazání, přepisování, odesílání). Destruktivní akce vyžadují vyšší úroveň potvrzení.

isConcurrencySafe() – říká engine, zda lze nástroj spouštět paralelně s jinými. Paralelní exekuce nástrojů je silná optimalizace, ale ne všechny nástroje to umožňují bezpečně.

interruptBehavior() – definuje, co se stane, když uživatel odešle novou zprávu zatímco nástroj běží. Dvě možnosti: cancel (zahodit) nebo block (počkat na dokončení).

prompt() – generuje popis nástroje pro AI model. Každý nástroj tedy sám říká modelu, jak ho má používat.

Celkem má kontrakt přes 20 metod a vlastností. To je neobvykle bohaté rozhraní – většina plugin systémů si vystačí s pěti.


Registr nástrojů – podmíněné načítání

Soubor tools.ts (390 řádků) je registr všech dostupných nástrojů. Ale není to jednoduchý seznam. Polovina nástrojů se načítá podmíněně:

Feature flagy rozhodují, zda nástroj vůbec existuje. Například SleepTool existuje pouze pokud je aktivní feature('PROACTIVE') nebo feature('KAIROS'). Pokud ne, proměnná je null a nástroj se nikdy neobjeví v seznamu.

Typ uživatele filtruje interní nástroje. REPLTool, ConfigTool a TungstenTool jsou dostupné pouze pro process.env.USER_TYPE === 'ant' (zaměstnanci Anthropicu).

Prostředí aktivuje platformově specifické nástroje. PowerShell se načte jen na Windows. LSP nástroj vyžaduje explicitní environment variable.

Samotné načítání používá require() místo statických importů – záměrně. Bundler (Bun) při statickém importu vloží kód do výsledného binárního souboru vždy. Podmíněný require() umožňuje dead code elimination – nástroj, který feature flag vypne, se fyzicky neobjeví ve výsledném buildu.

Funkce getAllBaseTools() vrací pole všech aktivních nástrojů. V komentáři stojí varování: „This MUST stay in sync with claude_code_global_system_caching.“ Důvod – Anthropic cachuje systémový prompt na serveru. Pokud by se seznam nástrojů neshodoval, cache by se neustále invalidovala.


Tři vrstvy nástrojů

Claude Code pracuje se třemi odlišnými kategoriemi nástrojů:

Vestavěné (built-in) – přímá součást kódu. BashTool, FileReadTool, FileEditTool a dalších přibližně 40 nástrojů. Mají plný přístup k internímu stavu a jsou optimalizovány pro rychlost.

MCP nástroje – přicházejí dynamicky od externích MCP serverů. Prochází Unicode sanitizací, mají vlastní oprávnění a jsou odstraněny ze seznamu, pokud je na ně nastavena deny pravidla.

Skill nástroje – uživatelem definované „dovednosti“ (vlastní příkazy). Jsou konfigurovatelné přes CLAUDE.md soubory a volají se přes /skill-name syntaxi.

Funkce assembleToolPool() slučuje všechny tři kategorie. Vestavěné nástroje mají přednost – pokud MCP server definuje nástroj se stejným jménem, použije se vestavěná verze. Důvod je bezpečnostní – MCP server by mohl přepsat FileEditTool vlastní verzí, která by obešla oprávnění.

Zajímavý detail: nástroje se řadí abecedně, ale vestavěné jako souvislý prefix. Komentář vysvětluje proč: prompt cache na serveru nastavuje breakpoint za posledním vestavěným nástrojem. Pokud by se MCP nástroj zařadil mezi vestavěné, invalidoval by celý cache.


Lazy loading – boj o každou milisekundu

Claude Code je terminálový nástroj a uživatelé očekávají okamžitou odezvu. Proto se klade extrémní důraz na rychlost startu.

Strategie je vícepólová:

Podmíněné importy. Místo import { SleepTool } from './tools/SleepTool' (vždy načte soubor) se používá:

const SleepTool = feature('PROACTIVE')
  ? require('./tools/SleepTool/SleepTool.js').SleepTool
  : null

Tím se soubor načte pouze když je feature aktivní.

Lazy factory funkce. Některé nástroje se řeší přes factory: const getTeamCreateTool = () => require('...'). Nástroj se načte až při prvním volání factory, ne při importu modulu.

Cirkulární závislosti. Komentáře vysvětlují důvod některých lazy importů: „Lazy require to break circular dependency: tools.ts -> TeamCreateTool -> … -> tools.ts.“ V projektu o 1 884 souborech jsou cyklické závislosti nevyhnutelné.

Monkey-patching prevence. V utility kódu (lockfile.ts) se knihovna proper-lockfile načítá lazy, protože její import automaticky monkey-patchuje fs modul přes graceful-fs, což stojí 8 milisekund. To je doba, kterou uživatel pocítí.


Služby – druhá vrstva architektury

Adresář services/ obsahuje 20 podadresářů a 16 samostatných souborů. Klíčové služby:

MCP klient (3 349 řádků) – spravuje připojení k externím nástrojovým serverům. Řeší reconnect, graceful shutdown (SIGINT -> SIGTERM -> SIGKILL s timeouty), Unicode sanitizaci a OAuth autentizaci.

Analytics – telemetrie s bezpečnostním typem AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS. Tento typ existuje jako psychologická bariéra pro vývojáře – před odesláním dat do telemetrie musí explicitně potvrdit, že neposílá citlivé údaje.

Compact – služba pro automatickou sumarizaci kontextu. Když se konverzace blíží limitu kontextového okna, služba automaticky komprimuje starší zprávy.

Hlas (voice.ts, 17 KB) – podpora hlasového vstupu s vlastním speech-to-text streamováním a detekcí klíčových slov.

Rate limiting – kompletní mock systém (30 KB) pro testování chování při překročení limitů API.


Oprávnění – čtyřúrovňový systém

Modulární architektura se projevuje i v systému oprávnění. Každý nástroj prochází čtyřvrstevným filtrem:

  1. Deny pravidla – globální zákaz na úrovni tool poolu. Nástroj se vůbec neobjeví v seznamu.
  2. isEnabled() – dynamická kontrola na úrovni modulu. Nástroj může být načtený, ale ne aktivní.
  3. validateInput() – kontrola vstupních parametrů. Například BashTool odmítne příliš dlouhé příkazy.
  4. checkPermissions() – nejjemnější vrstva. Rozhoduje na základě vstupu, kontextu, permission mode a uživatelských pravidel.

Navíc existuje auto-mode klasifikátor, který v plně automatickém režimu hodnotí bezpečnost každé akce. Pokud klasifikátor není dostupný (výpadek), Claude Code přechází do „try later“ režimu místo toho, aby akci povolil.


Proč to funguje

Modulární architektura Claude Code není samoúčelná. Řeší konkrétní problémy:

Nezávislé nasazení. Nový nástroj vyžaduje změnu jednoho adresáře a jednoho řádku v registru. Žádné změny v jádře.

Testovatelnost. Každý nástroj lze testovat izolovaně díky jasnému kontraktu. Existuje dokonce TestingPermissionTool, který se načte pouze v test prostředí.

Bezpečnost v hloubce. Čtyři vrstvy oprávnění, deny pravidla na úrovni poolu, sanitizace MCP vstupů – každá vrstva zachytí jiný typ hrozby.

Výkon. Lazy loading, podmíněné importy a dead code elimination zajišťují, že uživatel platí (v čase startu) pouze za funkce, které skutečně používá.

Cache stabilita. Pečlivé řazení nástrojů a oddělení statických/dynamických sekcí promptu minimalizuje invalidaci prompt cache, což šetří tokeny a zrychluje odpovědi.

Pro projekt o rozsahu 29 MB TypeScriptu, 1 884 souborech a 40+ modulárních nástrojích je tato architektura nezbytností. Bez ní by byl Claude Code neudržitelný monstrum. S ní je to – poměrně elegantní – monstrum.