QueryEngine — backed by a React/Ink terminal UI and a rich tool registry.
The QueryEngine
QueryEngine (src/QueryEngine.ts, ~46K lines) is the engine that drives every conversation. One instance is created per conversation; each submitMessage() call starts a new turn within the same session while preserving state — messages, file cache, token usage — across turns.
Key responsibilities:
The Tool-Call Loop
Every turn follows this sequence:1
User message submitted
submitMessage() is called with the user’s input. The message is normalized and appended to mutableMessages.2
System prompt assembled
fetchSystemPromptParts() and getUserContext() build the full system prompt, including memory content, working directory, and any custom prompts.3
API query
The
query() function streams a response from the Anthropic API. Streaming chunks are yielded to the UI in real time.4
Tool calls executed
If the response contains
tool_use blocks, each tool is run through the permission check, executed, and its result appended as a tool_result message.5
Loop or return
If tools were called, the model is queried again with the results. This repeats until the model emits a final text response with no tool calls (or
maxTurns is reached).Parallel Startup Optimization
Startup time is minimized by firing side-effects before heavy module evaluation begins inmain.tsx:
Lazy Loading
Two large native modules are deferred via dynamicimport() until they are actually needed:
This keeps the cold-start time low even on slower machines.
Feature Flags
Claude Code uses Bun’sbun:bundle feature-flag mechanism for dead-code elimination. Inactive flags are completely stripped at build time — the code doesn’t just branch, it’s removed from the bundle entirely.
Context Collection
Before every API call the system prompt is assembled from two sources:getSystemContext()— static environment facts: OS, shell, working directory, date/time, Claude Code version, available tools list, and project-levelCLAUDE.mdcontents.getUserContext()— dynamic per-turn context: memory prompt (fromloadMemoryPrompt()), coordinator context, and any appended system prompt provided via config.
The memory prompt is injected into the user context rather than the system prompt to keep the system prompt cache prefix stable across turns, which reduces API costs.