📄

Request My Resume

Thank you for your interest! To receive my resume, please reach out to me through any of the following channels:

Claude Code Source Deep Dive 04: REPL and AppState

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

REPL Control Plane Cover

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: • tasksforegroundedTaskIdviewingAgentTaskIdtoolPermissionContextmcp.clients / tools / resourcespluginsagentDefinitionstodossessionHooks

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:

tasksforegroundedTaskIdviewingAgentTaskIdagentNameRegistry

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.

AppState State Map

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.

REPL Control Plane Diagram

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: • TaskListV2TeammateViewHeader • 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: • useSwarmInitializationuseMailboxBridgeuseBackgroundTaskNavigation

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

Mermaid Diagram 1

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.

Mr. Guo Logo

© 2026 Mr'Guo

Twitter Github WeChat