# Agent Tracking with Task Subagent Types in Claude HUD: A Deep Dive into Transcript Parsing

> Discover how Claude HUD tracks agents by parsing transcript entries for Task subagent types. Learn about the JSON-L parsing and AgentEntry map for real-time updates.

- Repository: [Jarrod Watts/claude-hud](https://github.com/jarrodwatts/claude-hud)
- Tags: deep-dive
- Published: 2026-03-18

---

**Claude HUD implements agent tracking by parsing JSON-L transcript entries to detect `Task` tool uses, extracting `subagent_type` from the input payload, and maintaining a lifecycle-managed `AgentEntry` map that updates from "running" to "completed" upon receiving the corresponding tool result.**

The `jarrodwatts/claude-hud` repository provides a terminal heads-up display for Claude Code sessions. At its core, the system performs real-time **agent tracking with Task subagent types** by analyzing the session transcript stream. This mechanism enables the HUD to visualize when Claude spawns specialized sub-agents—such as search, write, or explore tasks—and monitor their execution status until completion.

## How Task Tool Detection Works in src/transcript.ts

The transcript parser in [`src/transcript.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/transcript.ts) processes the session log line-by-line. Within the `processEntry` function, the system identifies when Claude invokes a sub-agent through the `Task` tool.

### Detecting Task Tool Use Blocks

When the parser encounters a block where `type === 'tool_use'` and `name === 'Task'`, it triggers the agent creation path. This detection occurs at lines 94-108 in [`src/transcript.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/transcript.ts):

```typescript
if (block.type === 'tool_use' && block.name === 'Task') {
  const input = block.input as Record<string, unknown>;
  const agentEntry: AgentEntry = {
    id: block.id,
    type: (input?.subagent_type as string) ?? 'unknown',
    model: (input?.model as string) ?? undefined,
    description: (input?.description as string) ?? undefined,
    status: 'running',
    startTime: timestamp,
  };
  agentMap.set(block.id, agentEntry);
}

```

### Extracting Subagent Type from Input Payload

The parser extracts the `subagent_type` field from the tool's input payload at line 107. This value categorizes the agent's purpose—common values include `search`, `write`, `explore`, or `code`. If the field is absent, the system defaults to `'unknown'`.

## The AgentEntry Data Structure

The `AgentEntry` interface defined in [`src/types.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/types.ts) serves as the canonical data structure for tracked sub-agents:

```typescript
export interface AgentEntry {
  id: string;                // Same as the tool_use.id
  type: string;              // subagent_type from the Task payload
  model?: string;            // optional model name
  description?: string;      // optional textual description
  status: 'running' | 'completed';
  startTime: Date;
  endTime?: Date;
}

```

This structure enables the HUD to display rich metadata about each active sub-agent, including its specific type and execution duration.

## Tracking Agent Lifecycle: From Running to Completed

The system maintains agent state through a complete lifecycle, from initial detection through completion.

### Storing Agents in the Map

Upon detecting a `Task` tool use, the parser creates an `AgentEntry` and stores it in `agentMap` (a `Map<string, AgentEntry>`) using the tool's unique ID as the key. This occurs at lines 112-114 in [`src/transcript.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/transcript.ts):

```typescript
agentMap.set(block.id, agentEntry);

```

This mapping allows the system to correlate subsequent tool results with their originating agent.

### Updating Status on Tool Result

When the parser encounters a `tool_result` block, it checks whether the `tool_use_id` matches an entry in `agentMap`. If found, the system updates the agent's status to `"completed"` and records the `endTime`. This logic appears at lines 64-68:

```typescript
if (block.type === 'tool_result' && block.tool_use_id) {
  const agent = agentMap.get(block.tool_use_id);
  if (agent) {
    agent.status = 'completed';
    agent.endTime = timestamp;
  }
}

```

### Trimming to Recent Agents

After processing the entire transcript, the system retains only the most recent 10 agents to prevent memory bloat and maintain HUD clarity. This trimming occurs at line 69:

```typescript
result.agents = Array.from(agentMap.values()).slice(-10);

```

## Rendering Tracked Agents in the HUD

The `renderAgentsLine` function in [`src/render/agents-line.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/render/agents-line.ts) (lines 4-34) formats the tracked agents for terminal display. It selects currently running agents plus the two most recent completed agents, then generates a formatted string showing status icons, agent types, and elapsed time:

```typescript
const runningAgents = agents.filter(a => a.status === 'running');
const recentCompleted = agents.filter(a => a.status === 'completed').slice(-2);
const toShow = [...runningAgents, ...recentCompleted].slice(-3);

return toShow.map(formatAgent).join('\n');

```

This ensures the HUD always shows relevant active work while maintaining a compact display.

## Summary

- **Task Detection**: The parser in [`src/transcript.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/transcript.ts) identifies `tool_use` blocks with `name === 'Task'` to trigger agent creation.
- **Type Extraction**: The `subagent_type` field from the tool input determines the agent's categorical type (search, write, etc.).
- **Lifecycle Management**: Agents are stored in a `Map` keyed by tool-use ID, updated to `"completed"` status upon receiving the matching `tool_result`, and trimmed to the 10 most recent entries.
- **HUD Rendering**: The `renderAgentsLine` function displays running agents plus recent completions with status icons and timing information.

## Frequently Asked Questions

### What triggers the creation of an AgentEntry in Claude HUD?

An `AgentEntry` is created when the transcript parser encounters a `tool_use` block where the `name` property equals `"Task"`. This indicates Claude has invoked a sub-agent tool, prompting the system to initialize a new agent record with `"running"` status and capture metadata like `subagent_type` from the tool's input payload.

### How does the system distinguish between different subagent types?

The system extracts the `subagent_type` field from the `Task` tool's input object. This string value—such as `"search"`, `"write"`, `"explore"`, or `"code"`—is stored directly in the `AgentEntry.type` property. If the field is missing, the system defaults to `"unknown"` to ensure graceful handling of malformed or legacy tool calls.

### What happens when a Task subagent completes its execution?

When the sub-agent finishes, Claude emits a `tool_result` block containing the original `tool_use_id`. The parser looks up this ID in the `agentMap`, and if found, updates the corresponding `AgentEntry` by setting `status` to `"completed"` and recording the `endTime` timestamp. This change is immediately reflected in the HUD during the next render cycle.

### Why does Claude HUD only display the 10 most recent agents?

After processing the entire transcript, the system explicitly trims the agent list to the last 10 entries using `Array.from(agentMap.values()).slice(-10)`. This design prevents memory accumulation during long sessions and keeps the HUD interface uncluttered, ensuring users see only relevant recent activity rather than an overwhelming historical backlog.