Welcome back! In the previous chapter, Background Task Footer, we learned how to display a row of summary "pills" at the bottom of the screen.
Those pills are great for knowing that something is running, but they don't tell you what is actually happening.
Imagine driving a car. A light on your dashboard turns on. It tells you something is wrong, but not what. To find out, you need to pull over and open the hood.
The Background Task Footer is the dashboard light. It tells you @writer is thinking or build is running.
The Task Detail Dialog is opening the hood. It lets you see the logs, the errors, and the active thought process of an AI agent.
We use a Task Detail Dialogβa specialized window that pops up over your main content. It temporarily takes focus, allowing you to interact with that specific background process.
@writer pill spinning indefinitely.@writer is trying to write.
All detail views are wrapped in a generic <Dialog> component. This ensures they all look consistent (same border, same title bar, same keyboard shortcuts for closing).
Unlike a static error message, these dialogs are alive.
tail -f).Depending on what you are looking at, you might want to do different things:
How does the system switch from the footer to the dialog?
Let's look at ShellDetailDialog.tsx. This is the simplest type of dialog. It is used when the system runs a standard terminal command (like npm install) in the background.
We wrap everything in a Dialog. We also listen for keyboard events so the user can control the window.
// ShellDetailDialog.tsx simplified
export function ShellDetailDialog({ shell, onDone }) {
// Handle keys like Esc (close) or X (stop task)
const handleKeyDown = (e) => {
if (e.key === 'x') onKillShell();
};
return (
<Box flexDirection="column" onKeyDown={handleKeyDown}>
<Dialog
title="Shell details"
onCancel={onDone}
>
{/* Content goes here */}
</Dialog>
</Box>
);
}
Before showing the raw logs, we show a summary header. This uses standard Text components to show the command name and how long it has been running.
// Inside the render function
<Box flexDirection="column">
<Text>
<Text bold>Status:</Text>
<Text color="background">{shell.status}</Text>
</Text>
<Text>
<Text bold>Command:</Text>
{truncateToWidth(shell.command, 50)}
</Text>
</Box>
This is the most important part. We don't want to freeze the UI by reading a massive file synchronously. We use a helper function getTaskOutput which reads only the end ("tail") of the output file.
// Reads the last 8KB of the log file
async function getTaskOutput(shell) {
const path = getTaskOutputPath(shell.id);
const result = await tailFile(path, 8192);
return result; // contains { content: string }
}
We then use a React effect to poll this data repeatedly while the dialog is open:
useEffect(() => {
if (shell.status !== "running") return;
// Update output every second
const timer = setInterval(() => {
updateOutput();
}, 1000);
return () => clearInterval(timer);
}, [shell.status]);
When viewing an AI agent (like in AsyncAgentDetailDialog.tsx or InProcessTeammateDetailDialog.tsx), raw text logs aren't enough. We want to see the Structure of the AI's thoughts.
Instead of a wall of text, we parse the agent's state to show what "Tool" it is currently using.
// InProcessTeammateDetailDialog.tsx
<Box flexDirection="column">
<Text bold dimColor>Progress</Text>
{/* Loop through recent actions */}
{teammate.progress.recentActivities.map((activity, i) => (
<Text key={i}>
{/* Helper to render "Reading file..." or "Running command..." */}
{renderToolActivity(activity, tools, theme)}
</Text>
))}
</Box>
Note: You will learn more about how we render these specific activities in Tool Activity Renderer.
Often, you want to know: "What did I actually ask this agent to do?"
const displayPrompt = truncateToWidth(teammate.prompt, 300);
return (
<Box flexDirection="column" marginTop={1}>
<Text bold dimColor>Prompt</Text>
<Text wrap="wrap">{displayPrompt}</Text>
</Box>
);
Sometimes a task isn't running on your computer at allβit's running in the cloud. The RemoteSessionDetailDialog.tsx handles this.
Instead of showing a file log, it might offer a link to open the session in a browser, or a button to "Teleport" (connect your local terminal to that remote session).
// RemoteSessionDetailDialog.tsx
<Dialog title="Remote session">
<Text>Status: {session.status}</Text>
{/* Offer to open URL */}
<Link url={sessionUrl}>
<Text>{sessionUrl}</Text>
</Link>
<Text dimColor>Press 't' to teleport to this session</Text>
</Dialog>
Task Detail Dialogs act as the "inspector" for your system. They take the minimal information from the Footer and expand it into a full, interactive view.
Now that we can see the text status of our tasks, how do we make the status recognizable at a glance with colors and icons?
Next Chapter: Visual Status System
Generated by Code IQ