# How the oh-my-claudecode HUD Statusline Renders Real-Time Orchestration Metrics

> Discover how oh-my-claudecode renders real-time orchestration metrics by polling data sources and aggregating them into a concise, color-coded terminal statusline. Learn more.

- Repository: [Bellman/oh-my-claudecode](https://github.com/Yeachan-Heo/oh-my-claudecode)
- Tags: internals
- Published: 2026-03-27

---

**The oh-my-claudecode HUD renders real-time orchestration metrics by polling three independent JSON data sources—Claude Code transcripts, OMC runtime state files, and external APIs—then aggregating them into a declarative `HudRenderContext` that pure renderer functions convert into a concise, color-coded terminal statusline.**

The **HUD** (Heads-Up Display) in [oh-my-claudecode](https://github.com/Yeachan-Heo/oh-my-claudecode) is a lightweight terminal statusline that provides continuous visibility into multi-agent orchestration states. Unlike static logging, it maintains a live view of active agents, loop iterations, rate limits, and background tasks by re-rendering the entire pipeline on a configurable interval. Understanding how this real-time rendering pipeline works requires examining the three distinct data flows that feed the display.

## The Three Data Sources Driving the HUD

The HUD operates as a pure-function view over immutable JSON snapshots. It combines three independent data streams to build a complete picture of the orchestration state.

### Claude Code Transcript Stream

The primary data source is the live JSON stream from Claude Code (or a cached copy when stdin is a TTY). In [`src/hud/stdin.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/stdin.ts), the `readStdinCache()` function retrieves the latest transcript, while [`src/hud/transcript.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/transcript.ts) parses this into structured metrics:

- Active agents and their statuses
- Pending todos and thinking states  
- Tool-call, agent-call, and skill-call counters
- Pending permissions and session health tokens

### OMC Runtime State Files

Persistent state files written by various "modes" (Ralph, Ultrawork, Autopilot, PRD, and background tasks) provide loop-level orchestration data. The [`src/hud/omc-state.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/omc-state.ts) module exports read helpers that fetch JSON blobs from `~/.omc/state/`, while [`src/team/team-status.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/team/team-status.ts) aggregates worker heartbeats. These files contain:

- Loop counters and iteration limits
- PRD story IDs and autopilot modes
- Background task progress and session start times

### External Rate-Limit APIs

When `elements.rateLimits` is enabled, the HUD fetches Anthropic or z.ai usage statistics via [`src/hud/usage-api.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/usage-api.ts). Optional custom provider commands defined in [`src/hud/custom-rate-provider.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/custom-rate-provider.ts) allow integration with proprietary rate-limit buckets, returning 5-hour and weekly usage percentages.

## Entry Point and Watch Loop

The CLI command `omc hud` executes [`src/hud/index.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/index.ts). For continuous updates, the `--watch` flag invokes [`src/cli/hud-watch.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/cli/hud-watch.ts), which implements `runHudWatchLoop()`:

```typescript
// src/cli/hud-watch.ts (excerpt)
while (!shouldStop) {
  await options.hudMain(true, skipInit);
  skipInit = true;
  await new Promise(r => setTimeout(r, options.intervalMs));
}

```

This loop executes every `intervalMs` (default 1000ms), calling the main HUD function with `readStdinCache()` enabled. This architecture ensures the statusline updates even when the parent process’s stdin is a TTY, decoupling the display from the actual Claude Code process.

## Building the Render Context

The `main()` function in [`src/hud/index.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/index.ts) acts as the aggregation layer. It constructs a `HudRenderContext` object by querying all three data sources:

```typescript
const context: HudRenderContext = {
  // Transcript data
  activeAgents: transcriptData.agents.filter(a => a.status === "running"),
  todos: transcriptData.todos,
  toolCallCount: transcriptData.toolCallCount,
  agentCallCount: transcriptData.agentCallCount,
  skillCallCount: transcriptData.skillCallCount,
  thinkingState: transcriptData.thinkingState,
  pendingPermission: transcriptData.pendingPermission,
  
  // OMC state files
  ralph,
  ultrawork,
  prd,
  autopilot,
  
  // External metrics
  rateLimitsResult,
  customBuckets,
  
  // UI metadata
  cwd,
  modelName: getModelName(stdin),
  omcVersion,
  updateAvailable,
};

```

Rate-limit data is fetched only when enabled, and session summaries refresh via a fire-and-forget child process (`spawnSessionSummaryScript`) to avoid blocking the render loop.

## Rendering the Statusline Elements

All rendering logic resides in [`src/hud/render.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/render.ts). The function iterates over `HudConfig.elements` (populated from `~/.omc/config.json` or defaults) and dispatches to specialized renderers in `src/hud/elements/*` based on which metrics are enabled.

### Orchestration-Specific Renderers

The following element renderers display live orchestration metrics:

- **[`src/hud/elements/agents.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/agents.ts)** — Renders `renderAgentsByFormat()` for compact views or `renderAgentsMultiLine()` for detailed agent listings, showing type codes and durations.
- **[`src/hud/elements/ralph.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/ralph.ts)** — Displays loop iterations (`Rα1/7`) and applies warning colors when crossing `thresholds.ralphWarning`.
- **[`src/hud/elements/autopilot.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/autopilot.ts)** — Shows autopilot state, taking precedence over Ralph when both modes are active.
- **[`src/hud/elements/background.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/background.ts)** — Lists running background jobs from `readHudState()`, such as `git-clone` operations or custom scripts.
- **[`src/hud/elements/call-counts.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/call-counts.ts)** — Aggregates `tool_use`, `agent`, and `skill` call totals for the current turn.
- **[`src/hud/elements/todos.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/todos.ts)** — Highlights pending todo items with the current task emphasized.
- **[`src/hud/elements/session.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/session.ts)** — Displays session duration and health badges (🟢/🟡/🔴).
- **[`src/hud/elements/thinking.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/thinking.ts)** — Shows a "thinking" indicator when the model is generating responses.
- **[`src/hud/elements/limits.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/limits.ts)** — Renders 5-hour and weekly usage percentages as numeric values or progress bars.
- **[`src/hud/elements/context.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/context.ts)** — Displays the percentage of the model's context window consumed.

The renderer respects `HudConfig.maxWidth` and `wrapMode` settings, joining header elements with ` | ` separators and truncating or wrapping based on terminal constraints.

## Achieving Real-Time Visibility

Because the watch loop re-executes the entire pipeline each tick, the HUD achieves real-time synchronization through file-system polling and API caching:

1. **Agent state changes** appear immediately when `transcript.jsonl` gains a new "running" entry.
2. **Ralph/Autopilot iterations** update as `~/.omc/state/*/ralph.json` or [`autopilot.json`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/autopilot.json) files are rewritten by the respective modes.
3. **Rate-limit bars** refresh every `usageApiPollIntervalMs` (default 90 seconds) via `getUsage()`.
4. **Background task completion** removes entries from `readHudState()` results instantly.

This pull-based architecture means the HUD never holds persistent state; each render cycle is idempotent, reading the latest JSON snapshots and producing a fresh statusline.

## Usage Examples

```bash

# One-off render (used by shell prompts)

omc hud

# Continuous live view with 0.5s refresh

omc hud --watch --interval 500

# Minimal preset for narrow terminals

omc hud --preset minimal

# Force custom width and wrapping

omc hud --max-width 80 --wrap-mode wrap

```

## Summary

- The HUD aggregates three data flows: Claude Code transcripts ([`src/hud/transcript.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/transcript.ts)), OMC runtime state files ([`src/hud/omc-state.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/omc-state.ts)), and external rate-limit APIs ([`src/hud/usage-api.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/usage-api.ts)).
- [`src/cli/hud-watch.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/cli/hud-watch.ts) implements `runHudWatchLoop()` to re-render every 1000ms by default.
- [`src/hud/index.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/index.ts) builds a `HudRenderContext` containing active agents, loop states, and usage metrics.
- [`src/hud/render.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/render.ts) dispatches to element-specific renderers in `src/hud/elements/` to generate the final statusline.
- The system uses a stateless, pull-based architecture where each tick reads fresh JSON snapshots to ensure real-time accuracy.

## Frequently Asked Questions

### How does the HUD handle stdin when running in watch mode?

When invoked with `--watch`, the HUD reads from `readStdinCache()` in [`src/hud/stdin.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/stdin.ts) rather than blocking on stdin. This allows the statusline to update continuously even when the parent process is a TTY, as the watch loop accesses cached transcript data written by the main Claude Code process.

### Where are the Ralph and Autopilot loop counters stored?

Loop iteration data is persisted in JSON files under `~/.omc/state/` (specifically [`ralph.json`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/ralph.json) and [`autopilot.json`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/autopilot.json)). The [`src/hud/omc-state.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/omc-state.ts) module provides type-safe read helpers, while [`src/hud/elements/ralph.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/ralph.ts) and [`src/hud/elements/autopilot.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/elements/autopilot.ts) parse these files to render counters like `Rα1/7` and apply threshold-based color coding.

### Can I customize which metrics appear in the statusline?

Yes. The HUD respects the `elements` configuration object in `~/.omc/config.json`. Each boolean flag (e.g., `agents`, `rateLimits`, `background`) controls whether [`src/hud/render.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/hud/render.ts) invokes the corresponding renderer in `src/hud/elements/`. You can also apply presets using `omc hud --preset minimal` to quickly toggle common metric combinations.

### How often does the HUD fetch external rate-limit data?

By default, the Anthropic/z.ai usage API is polled every 90 seconds (`usageApiPollIntervalMs`). This cached value is then read from `rateLimitsResult` in the render context on every tick, ensuring the statusline remains responsive while respecting API rate limits.