Digital Strategy Review | 2026
Claude Code Source Code Walkthrough 04: Revisiting REPL.tsx and AppStateStore.ts — Why the UI Layer Looks the Way It Does
By Uncle Fruit · Reading Time / 8 Min

Preface
We’ve reached the fourth installment, and the groundwork laid in previous articles finally comes together.
If you jump straight into REPL.tsx, it’s easy to feel it’s absurdly large; if you look at AppStateStore.ts first, you might wonder why so much state is packed into one place. However, once you have the context from the first three parts, these two files become quite logical. They aren’t just standard UI layers; they are the control plane for the entire Claude Code agent runtime.
In other words, this article aims to answer: Why does a multi-agent system inside a terminal require a master control structure that looks “like a UI, but is more than just a UI”?
They are not just standard UI layers; they are the unified control plane for the entire Claude Code agent runtime.
01
I. First, look at AppStateStore.ts: It’s not page state, it’s session-level runtime state
This section is worth reading first. If you view AppStateStore.ts merely as a container for page state, many design choices will seem bloated. But once you view it as a session-level runtime store, everything clicks.
The defining characteristic of AppState is that it doesn’t just manage display logic.
It carries three categories of state simultaneously:
01 Interaction State
02 Execution State
03 Collaboration State
1. Interaction State
Includes:
• Current settings
• Status line
• Expanded view
• Footer selection
• Prompt suggestion
• Notifications
• Elicitation queue
• thinkingEnabled
This part looks like typical UI state.
2. Execution State
Includes:
• tasks
• foregroundedTaskId
• viewingAgentTaskId
• toolPermissionContext
• mcp.clients / tools / resources
• plugins
• agentDefinitions
• todos
• sessionHooks
This part is clearly no longer “page state,” but a core object repository for the session runtime.
3. Collaboration State
Includes:
• agentNameRegistry
• Teammate-related view states
• Remote connection status
• Bridge status
• Computer use / bagel / tungsten related states
In essence, AppState is:
The unified state tree of the “world” inhabited by the current Claude Code session.
02
II. Why tasks must be at the top level of AppState
This is the most critical point for understanding the entire UI architecture.
Claude Code’s task system isn’t hidden inside a service; it is placed directly at the top level of the state tree:
• tasks
• foregroundedTaskId
• viewingAgentTaskId
• agentNameRegistry
This leads directly to several outcomes:
01 Background agents can be consumed directly by the UI. 02 Teammates within the same process can be switched and viewed. 03 Remote tasks can be integrated into a unified list. 04 Notifications, foregrounding, closing, and resuming can all be attached to the same interaction mechanism.
Without this layer, the REPL could not unify the multi-agent control experience.

Once you understand AppStateStore, looking back at the scale of the REPL, you realize it’s not just a case of a “too-large UI file.”
03
III. Why REPL.tsx is so large: It’s not a chat window, it’s a console
Now, looking at REPL.tsx, it becomes clear why it has grown into a massive file.
It must handle all of these simultaneously:
• Prompt input • Message rendering • Query initiation and streaming event reception • Command queue • Permission dialogs • Sandbox permissions • Background task navigation • Swarm initialization • Mailbox bridge • Merged tools / merged commands • MCP / plugin / IDE integration • Teammate views • Task lists • Various notifications and callouts
This isn’t what a “chat component” should do, but it is exactly what an agent control plane must do.
04
IV. The core role of the REPL: Translating different execution entities into a unified interaction experience
From an architectural perspective, the REPL performs at least four types of translation.
1. Translating the query loop into a streaming interface
query(...) is a low-level asynchronous generator; the REPL is responsible for turning it into:
• Message streams
• Spinners
• Progress bars
• Visualization of thinking / tool progress
2. Translating task runtime into user-understandable objects
Tasks are just state and output files at the bottom level, but the REPL turns them into: • Task lists • Teammate views • Foregrounded transcripts • Completion notifications
3. Translating the permission system into a unified approval experience
Tool permissions, sandbox permissions, and worker permissions come from different sources at the bottom level, but the REPL is responsible for consolidating them into dialogs / request overlays that the user can handle.
4. Translating scattered capability sources into a single input experience
Commands, MCPs, plugins, skills, slash commands, and queued commands are originally multiple paths, but the REPL ultimately allows the user to perceive and use them through a single input interface.
05
V. Why structures like useMergedTools and useMergedCommands exist
These two hooks perfectly illustrate the UI layer’s philosophy in Claude Code.
Because in the runtime, the sources of capability are not singular: • Local built-in tools • MCP tools • Plugin commands • MCP commands
If the UI layer handled these sources separately, the interaction would be extremely fragmented. Therefore, the REPL needs a unified “view of currently available capabilities.”
This is why previous articles emphasized: • Tools are a dynamic capability surface. • Commands are a dynamic capability surface. • Agent definitions are also a dynamic capability surface.
One of the REPL’s responsibilities is to combine these dynamic surfaces into the operational world the user actually perceives.

The REPL’s duty is not just to render model output, but to translate different execution entities into a set of interaction experiences that the user can master.
06
VI. Why teammate views and task views must be in the REPL
Many systems completely separate “background tasks” from the “chat interface.” Claude Code does not.
The reason is simple: In an agent runtime, background tasks are not appendages; they are part of the main system.
That’s why you see the following in the REPL:
• TaskListV2
• TeammateViewHeader
• Viewing agent bootstrap
• Background task navigation
This means the REPL doesn’t just display the main agent’s conversation; it displays all active execution entities in the entire session and their relationships.
This step is crucial because it solves the hardest problem in multi-agent products:
How does the user understand that “there is more than one agent working in the system right now”?
Claude Code’s answer is: Don’t open a second interface; unify them directly back into the REPL control plane.
07
VII. Why the permission UI feels so “heavy”
Because in Claude Code, permissions are not occasional pop-ups; they are part of the core control loop.
REPL.tsx coordinates:
• PermissionRequest
• Sandbox permission queue
• Worker sandbox permission
• Prompt queue
• Elicitation queue
This is not UI over-engineering; it is the natural result of the complexity of the agent runtime mentioned earlier: • The main agent requests permissions. • Worker agents also request permissions. • Some permissions come from tools. • Some permissions come from the sandbox/network. • Some permissions come from MCP elicitation.
Without a unified queue and aggregated UI, the entire system would be unusable.
08
VIII. Why the REPL needs to directly understand swarm / mailbox / backgrounding
This is also worth noting.
It does not completely encapsulate multi-agent collaboration in the backend; instead, it explicitly integrates:
• useSwarmInitialization
• useMailboxBridge
• useBackgroundTaskNavigation
This shows that Claude Code’s product design is not “multi-agent backend, pretending to be single-agent frontend,” but rather an acknowledgment that collaboration itself is a first-class experience.
Therefore, the REPL must understand: • That a teammate is running. • Who is waiting for permission. • Which agent is currently being viewed. • Whether any background tasks have been completed.
Only in this way can multi-agent systems avoid becoming a situation where “a lot of things are happening in the background, but the user is clueless.”
09
IX. Reverse-engineering UI form from state design
You can directly infer why the REPL looks the way it does from a few fields:
tasks
Indicates the UI must have a task list and task navigation.
foregroundedTaskId
Indicates that background tasks can be switched back to the main stage.
viewingAgentTaskId
Indicates that agent transcripts are switchable objects, not just the main conversation.
agentNameRegistry
Indicates the system supports routing from names to agents; collaboration is not anonymous.
toolPermissionContext
Indicates that permissions are not local logic, but global runtime conditions.
mcp / plugins / agentDefinitions
Indicates that the “currently available capabilities” in the REPL are not statically hardcoded.
Thus, you find that the complexity of the UI layer is not an accident, but a natural requirement of the state model.
10
X. Understanding the relationship between REPL and AppState in one diagram

11
XI. If you only take away one summary
AppStateStore.ts defines the session-level runtime state model. REPL.tsx acts as the unified interaction control plane.
Their complexity is not because the UI code is scattered, but because Claude Code has unified all of the following into a single control plane: • Main agent • Sub-agents • Teammates • Background tasks • Remote tasks • Permission approvals • Plugins / MCP / tools • Multiple view switching
From a product perspective, this makes Claude Code feel like an “operating system shell inside a terminal.” From a source code perspective, this is why both the REPL and AppState must be structured the way they are.
12
XII. Conclusion of the series
With this, the four articles form a complete reading path:
01 cli.tsx + main.tsx: How the system is assembled.
02 query.ts + tools.ts + toolOrchestration.ts: How the system executes.
03 AgentTool + tasks + swarm: How the system turns agents into runtime objects.
04 REPL.tsx + AppStateStore.ts: How the system presents a complex runtime to the user.
If you have followed these four articles, looking back at the Claude Code src directory, it no longer looks like a pile of giant files, but rather like a multi-agent terminal runtime with very clear boundaries.