How the oh-my-claudecode HUD Statusline Renders Real-Time Orchestration Metrics
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 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, the readStdinCache() function retrieves the latest transcript, while 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 module exports read helpers that fetch JSON blobs from ~/.omc/state/, while 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. Optional custom provider commands defined in 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. For continuous updates, the --watch flag invokes src/cli/hud-watch.ts, which implements runHudWatchLoop():
// 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 acts as the aggregation layer. It constructs a HudRenderContext object by querying all three data sources:
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. 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— RendersrenderAgentsByFormat()for compact views orrenderAgentsMultiLine()for detailed agent listings, showing type codes and durations.src/hud/elements/ralph.ts— Displays loop iterations (Rα1/7) and applies warning colors when crossingthresholds.ralphWarning.src/hud/elements/autopilot.ts— Shows autopilot state, taking precedence over Ralph when both modes are active.src/hud/elements/background.ts— Lists running background jobs fromreadHudState(), such asgit-cloneoperations or custom scripts.src/hud/elements/call-counts.ts— Aggregatestool_use,agent, andskillcall totals for the current turn.src/hud/elements/todos.ts— Highlights pending todo items with the current task emphasized.src/hud/elements/session.ts— Displays session duration and health badges (🟢/🟡/🔴).src/hud/elements/thinking.ts— Shows a "thinking" indicator when the model is generating responses.src/hud/elements/limits.ts— Renders 5-hour and weekly usage percentages as numeric values or progress bars.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:
- Agent state changes appear immediately when
transcript.jsonlgains a new "running" entry. - Ralph/Autopilot iterations update as
~/.omc/state/*/ralph.jsonorautopilot.jsonfiles are rewritten by the respective modes. - Rate-limit bars refresh every
usageApiPollIntervalMs(default 90 seconds) viagetUsage(). - 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
# 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), OMC runtime state files (src/hud/omc-state.ts), and external rate-limit APIs (src/hud/usage-api.ts). src/cli/hud-watch.tsimplementsrunHudWatchLoop()to re-render every 1000ms by default.src/hud/index.tsbuilds aHudRenderContextcontaining active agents, loop states, and usage metrics.src/hud/render.tsdispatches to element-specific renderers insrc/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 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 and autopilot.json). The src/hud/omc-state.ts module provides type-safe read helpers, while src/hud/elements/ralph.ts and 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →