乐于分享
好东西不私藏

ClaudeHUD源码解析:构建一个高效的ClaudeCode状态仪表盘

ClaudeHUD源码解析:构建一个高效的ClaudeCode状态仪表盘

本文深入剖析 Claude Code 生态中热门的终端状态仪表盘插件 ClaudeHUD 的源码实现。从无状态进程架构、管道过滤器数据流、会话转录解析、OAuth认证与用量API调用、到ANSI颜色渲染管线,完整拆解一个仅用纯TypeScript、无第三方运行时依赖构建的高效CLI HUD的设计思路与工程实践。全文包含9个核心模块的逐行源码分析、3张Mermaid时序图和可复现的配置指南,适合对ClaudeCode插件开发或终端工具体验设计感兴趣的开发者阅读。

目录

  1. 概述  1.1 项目背景  1.2 为什么需要ClaudeHUD  1.3 技术定位
  2. 核心架构  2.1 整体数据流  2.2 模块拓扑  2.3 状态行渲染管线
  3. 源码分析  3.1 入口与主控流(index.ts)  3.2 标准输入解析(stdin.ts)  3.3 会话转录解析(transcript.ts)  3.4 配置管理系统(config.ts)  3.5 Git状态采集(git.ts)  3.6 用量API调用(usage-api.ts)  3.7 渲染管线详解(render/)  3.8 颜色系统(colors.ts)  3.9 配置计数(config-reader.ts)
  4. 功能详解  4.1 上下文窗口可视化  4.2 用量限额追踪  4.3 工具活动监控  4.4 子代理状态追踪  4.5 Todo进度展示  4.6 Git工作区状态
  5. 技术亮点  5.1 无状态进程架构  5.2 文件缓存策略  5.3 macOS Keychain集成  5.4 上下文窗口自动压缩预算  5.5 防御式配置合并  5.6 上下文百分比计算覆盖缓存Token
  6. 实践指南  6.1 安装与配置  6.2 布局定制  6.3 常见问题排查
  7. 总结参考文献

1. 概述

ClaudeHUD是ClaudeCode生态中一个精巧的状态行插件,它利用ClaudeCode原生的statusline API,在终端输入行下方实时呈现会话关键指标——上下文窗口使用率、用量限额消耗、工具调用活动、子代理运行状态、Todo进度以及Git工作区情况。

与传统的tmux状态栏或多窗口方案不同,ClaudeHUD直接嵌入ClaudeCode的进程输入输出流中,每次渲染都是一个独立进程,通过stdin接收JSON状态数据,经由纯TypeScript逻辑计算后输出ANSI转义序列到stdout显示。这种设计使得它无需任何外部依赖即可在任何终端中工作。

1.1 项目背景

ClaudeCode作为CLI原生的AI编程助手,具备强大的工具调用和子代理编排能力。但在高强度使用中,用户面临三个痛点:

  • 上下文窗口何时将满无法直观感知(autocompact触发时可能打断当前任务流程)
  • 用量限额消耗进度不透明(Pro/Max/Team订阅有5小时和7天双重限制)
  • 子代理和工具调用活动无法追踪(多达10+个并发子代理的场景)

ClaudeHUD通过在终端底部固定显示一行状态信息,解决了上述全部问题。

1.2 为什么需要ClaudeHUD

ClaudeHUD给出的答案很直接:把最重要的信息压缩到一行里,永远可见,不需要用户做任何额外操作。

它呈现的信息可以分为三层:

  • 核心层(默认可见):模型名称、项目路径、Git分支、上下文窗口条形图、用量限额百分比和倒计时
  • 活动层(可选启用):工具调用列表、子代理运行状态、Todo进度
  • 环境层(可选启用):CLAUDE.md数量、规则数、MCP服务器数、Hooks数量、会话时长、内存占用

1.3 技术定位

从技术角度看,ClaudeHUD是一个无状态的管道过滤器(pipe filter):ClaudeCode每隔约300ms向其stdin推送一份JSON状态快照,ClaudeHUD解析后渲染为一行或多行ANSI格式文本输出到stdout,ClaudeCode将其显示在终端输入行下方。

2. 核心架构

2.1 整体数据流

ClaudeHUD作为独立进程运行,每次渲染周期内完成全部数据采集和渲染计算。进程退出后状态不保留,下次渲染时重新启动。这种短生命周期设计避免了内存泄漏和状态腐化问题。

2.2 模块拓扑

从源码结构看,ClaudeHUD由以下核心模块组成:

  • index.ts — 主控流:组装依赖,编排数据采集和渲染
  • stdin.ts — 标准输入解析:读取JSON快照,计算上下文百分比
  • transcript.ts — 会话转录解析:逐行解析JSONL文件,提取工具/代理/Todo
  • config.ts — 配置管理:从~/.claude/plugins/claude-hud/config.json加载并合并默认值
  • git.ts — Git状态采集:执行git子进程获取分支、脏状态、文件统计
  • usage-api.ts — 用量API调用:通过macOS Keychain获取OAuth凭证,调用Anthropic用量API
  • config-reader.ts — 配置计数:扫描CLAUDE.md、规则、MCP、Hooks文件
  • render/ — 渲染管线:将结构化数据转换为ANSI格式文本行
  • constants.ts — 全局常量(仅autocompact缓冲百分比)
  • types.ts — TypeScript类型定义

2.3 状态行渲染管线

渲染流程的核心设计是两段式布局:头部(项目、上下文、用量)和活动尾部(工具、代理、Todo)。头部始终显示,活动行默认隐藏,由用户通过/claude-hud:configure选择启用。

3. 源码分析

3.1 入口与主控流(index.ts)

exportasyncfunctionmain(overrides: Partial<MainDeps> = {}): Promise<void> {constdepsMainDeps = {    readStdin, parseTranscript, countConfigs, getGitStatus,    getUsage, loadConfig, parseExtraCmdArg, runExtraCmd, render,now() =>Date.now(), logconsole.log, ...overrides,  };try {const stdin = await deps.readStdin();if (!stdin) { deps.log('[claude-hud] Initializing...'); return; }const transcriptPath = stdin.transcript_path ?? '';const transcript = await deps.parseTranscript(transcriptPath);const { claudeMdCount, rulesCount, mcpCount, hooksCount } =await deps.countConfigs(stdin.cwd);const config = await deps.loadConfig();const gitStatus = config.gitStatus.enabled      ? await deps.getGitStatus(stdin.cwd) : null;const usageData = config.display.showUsage !== false      ? await deps.getUsage() : null;const extraCmd = deps.parseExtraCmdArg();const extraLabel = extraCmd ? await deps.runExtraCmd(extraCmd) : null;const sessionDuration = formatSessionDuration(transcript.sessionStart, deps.now);constctxRenderContext = { stdin, transcript, claudeMdCount,      rulesCount, mcpCount, hooksCount, sessionDuration, gitStatus,      usageData, config, extraLabel };    deps.render(ctx);  } catch (error) {    deps.log('[claude-hud] Error:',      error instanceofError ? error.message : 'Unknown error');  }}

设计要点:

  • 依赖注入:MainDeps接口允许测试时注入mock实现,所有外部依赖(文件I/O、git子进程、API调用)均可替换
  • 条件数据采集:Git状态仅在gitStatus.enabled时采集,用量数据仅在display.showUsage不为false时获取,避免不必要的系统调用开销
  • 错误隔离:整个主流程包裹在try/catch中,单个模块失败不会导致整个HUD崩溃

3.2 标准输入解析(stdin.ts)

exportfunctiongetContextPercent(stdin: StdinData): number {const usage = stdin.context_window?.current_usage;const size = stdin.context_window?.context_window_size;if (!usage || !size || size <= AUTOCOMPACT_BUFFERreturn0;const totalTokens =    (usage.input_tokens ?? 0) +    (usage.cache_creation_input_tokens ?? 0) +    (usage.cache_read_input_tokens ?? 0);returnMath.min(100Math.round(    ((totalTokens + AUTOCOMPACT_BUFFER) / size) * 100));}

上下文百分比计算的核心逻辑。AUTOCOMPACT_BUFFER是一个关键常量,值为0.225 * context_window_size(约22.5%),来源于社区对ClaudeCode自动压缩行为的经验观察。

公式为:percent = (input_tokens + cache_creation_tokens + cache_read_tokens + 22.5%) / context_window_size * 100

加入22.5%缓冲区的理由是:ClaudeCode在上下文达到约77.5%时触发autocompact,因此当显示百分比接近100%时实际上已经达到了触发的临界值。这个缓冲让百分比更具预警意义。

3.3 会话转录解析(transcript.ts)

转录文件是ClaudeCode会话期间写入的JSONL(每行一个JSON对象),记录了所有工具调用、工具结果和Todo状态变更。解析器逐行读取这个文件并维护三个数据结构:

  • toolMap: Map<string, ToolEntry> — 工具ID到工具条目的映射
  • agentMap: Map<string, AgentEntry> — 代理ID到代理条目的映射
  • latestTodos: TodoItem[] — 最新的Todo列表

关键解析逻辑:

for (const block of content) {if (block.type === 'tool_use' && block.id && block.name) {if (block.name === 'Task') {// 识别为子代理启动      agentMap.set(block.id, { id, type: input.subagent_type, ... });    } elseif (block.name === 'TodoWrite') {// 更新Todo列表      latestTodos.length = 0;      latestTodos.push(...input.todos);    } else {// 普通工具调用      toolMap.set(block.id, { id, name, targetextractTarget(...), ... });    }  }if (block.type === 'tool_result' && block.tool_use_id) {// 标记工具/代理完成  }}

其中extractTarget函数根据工具类型提取有意义的目标信息:Read/Write/Edit提取文件路径,Glob和Grep提取搜索模式,Bash提取命令前30个字符。

3.4 配置管理系统(config.ts)

配置系统使用防御式合并策略:用户配置通过JSON.parse读取后进行逐字段验证和类型检查,无效值静默回退到默认值。

functionmergeConfig(userConfig: Partial<HudConfig>): HudConfig {const lineLayout = validateLineLayout(migrated.lineLayout)    ? migrated.lineLayout : DEFAULT_CONFIG.lineLayout;// ...逐字段验证和合并const display = {showToolstypeof migrated.display?.showTools === 'boolean'      ? migrated.display.showTools : DEFAULT_CONFIG.display.showTools,// ...每个字段独立验证  };}

这种设计避免了用户配置文件中一个拼写错误导致整个HUD失效的问题。JSON语法错误、无效值、缺失字段都通过回退默认值的方式优雅降级。

3.5 Git状态采集(git.ts)

exportasyncfunctiongetGitStatus(cwd?: string): Promise<GitStatus | null> {const { stdout: branchOut } = awaitexecFileAsync('git',    ['rev-parse''--abbrev-ref''HEAD'],    { cwd, timeout1000encoding'utf8' });// 获取脏状态和文件统计const { stdout: statusOut } = awaitexecFileAsync('git',    ['--no-optional-locks''status''--porcelain'],    { cwd, timeout1000encoding'utf8' });// 获取ahead/behind计数const { stdout: revOut } = awaitexecFileAsync('git',    ['rev-list''--left-right''--count''@{upstream}...HEAD'],    { cwd, timeout1000encoding'utf8' });}

Git状态采集通过三个独立的git子进程完成。每个调用都设置了1000ms超时,避免在网络挂载目录或损坏的git仓库中阻塞渲染管线。使用--no-optional-locks标志防止与用户正在执行的git操作发生锁竞争。

文件统计解析采用Starship兼容格式:--porcelain输出的XY状态码中,??表示untracked,A表示added,D表示deleted,M/R/C表示modified。

3.6 用量API调用(usage-api.ts)

这是整个项目中最复杂的模块,处理OAuth认证、API调用、缓存和错误恢复。

认证流程采用两级回退:优先尝试macOS Keychain(ClaudeCode 2.x的凭证存储位置),失败后尝试文件系统上的.credentials.json(旧版本兼容)。Keychain调用使用execFileSync执行/usr/bin/security命令,具备超时保护(5000ms)和失败退避(60000ms),防止每次渲染都触发Keychain权限弹窗。

缓存策略分为两级:

  • 成功结果:60秒TTL,减少API调用频率
  • 失败结果:15秒TTL,更快重试但避免请求风暴

3.7 渲染管线详解(render/)

渲染入口render/index.ts根据布局模式分发:

  • expanded模式(默认):多行布局,第一行显示项目和Git信息,第二行显示上下文和用量,后续行显示环境和活动
  • compact模式:单行布局,所有信息压缩在一行内
exportfunctionrender(ctx: RenderContext): void {const headerLines = lineLayout === 'expanded'    ? renderExpanded(ctx) : renderCompact(ctx);const activityLines = collectActivityLines(ctx);// 合并输出,每行以RESET开头确保颜色隔离for (const line of [...headerLines, ...activityLines]) {console.log(`${RESET}${line.replace(/ /g, ' ')}`);  }}

一个值得注意的细节:所有空格都被替换为(不换行空格),防止终端在空格处进行自动换行导致状态行布局错乱。

工具活动行(tools-line.ts)的渲染逻辑:

  • 显示最近2个运行中的工具(黄色◐标记)
  • 显示完成工具的名称和调用次数(绿色✓标记,最多4种工具类型)

代理活动行(agents-line.ts):

  • 混合显示运行中代理和最近完成的2个代理(最多3个)
  • 显示代理类型、模型、描述和已用时间

Todo进度行(todos-line.ts):

  • 显示当前in_progress状态的Todo项及其进度(已完成/总数)
  • 全部完成时显示✓ All todos complete

3.8 颜色系统(colors.ts)

exportfunctiongetContextColor(percent: number): string {if (percent >= 85returnRED;if (percent >= 70returnYELLOW;returnGREEN;}

颜色系统遵循交通信号灯直觉:绿色(安全)、黄色(警告,70%+)、红色(危险,85%+)。上下文条形图使用实心块(前景色)和半透明块(dim色)的组合,10个字符宽度提供0-100%的精度。

3.9 配置计数(config-reader.ts)

countConfigs函数扫描三类ClaudeCode配置文件:

  • CLAUDE.md:用户级(~/.claude/CLAUDE.md)和项目级(cwd/CLAUDE.md、cwd/.claude/CLAUDE.md等)各计1个
  • 规则文件(.md):用户级(~/.claude/rules/)和项目级(cwd/.claude/rules/)递归计数
  • MCP服务器:从settings.json、.claude.json、.mcp.json中提取mcpServers对象的所有key,支持去重
  • Hooks:从settings.json中提取hooks对象的所有key计数

4. 功能详解

4.1 上下文窗口可视化

上下文窗口以10字符条形图展示,颜色根据使用率变换:

  • 低于70%:绿色,会话空间充足
  • 70%-85%:黄色,需要注意
  • 85%以上:红色,即将触发autocompact

当使用率超过85%时,自动显示token详情(输入token数和缓存token数),帮助用户判断哪些内容占据了上下文空间。

显示格式支持四种模式:百分比(45%)、token数(45k/200k)、剩余百分比(55% remaining)、组合(45% (45k/200k))。

4.2 用量限额追踪

用量追踪是Pro/Max/Team订阅用户的专属功能。ClaudeHUD从Anthropic用量API获取5小时和7天两个窗口的利用率数据。

默认显示5小时窗口和上下文使用率共享第二行:

Context █████░░░░░ 45% | Usage ██░░░░░░░░ 25% (130m / 5h)

当7天利用率超过阈值(默认80%)时追加显示:

... | ██████████ 85%(2d / 7d)

重置时间支持三种显示模式:相对倒计时(resets in 2h 30m)、绝对时间(resets at 14:30)、两者兼有。

4.3 工具活动监控

工具活动行展示两类信息:

  • 运行中的工具:黄色◐前缀,显示工具名和目标(文件路径或搜索模式)
  • 已完成的工具:绿色✓前缀,按调用次数降序排列,最多显示4种
◐ Edit: auth.ts | ✓ Read ×3 | ✓ Grep ×2

工具目标路径超过20字符时自动截断为.../filename格式。

4.4 子代理状态追踪

代理行混合显示运行中代理(黄色◐)和最近完成的代理(绿色✓),最多显示3个:

◐ explore[haiku]Findingauthcode (215s)

每个代理显示5个信息维度:状态图标、类型标签(品红色)、模型标签(dim色)、描述(截断至40字符)、已用时间(格式化为m ss)。

4.5 Todo进度展示

Todo行实时反映ClaudeCode内置任务追踪的状态:

▸ Fix authentication bug(2/5)

优先级逻辑为:如果有in_progress状态的Todo,显示当前项和进度;如果全部完成,显示完成提示;无活动Todo时隐藏整行。

4.6 Git工作区状态

Git状态显示在项目路径后,使用git:(branch)格式:

  • 无修改:git:(main)
  • 有未提交修改:git:(main*)
  • 显示ahead/behind:git:(main ↑2 ↓1)
  • 文件变更统计:git:(main* !3 +1 ?2)(3个修改、1个新增、2个未追踪)

5. 技术亮点

5.1 无状态进程架构

ClaudeHUD每次渲染都是全新的Node.js进程。这种设计有几个优势:

  • 没有内存泄漏累积——进程在渲染完成后退出,操作系统回收所有内存
  • 配置热加载——每次渲染都重新读取config.json,配置变更即时生效,无需重启
  • 故障隔离——单次渲染崩溃不影响后续渲染

代价是每次都需要重新执行git status、读取transcript文件、发起API调用等I/O操作。通过文件缓存(usage-api)和超时控制(git 1000ms)有效缓解了这个开销。

5.2 文件缓存策略

由于进程不保留内存状态,usage-api使用文件系统作为跨渲染的缓存介质。缓存文件位于~/.claude/plugins/claude-hud/.usage-cache.json,包含序列化的UsageData对象和时间戳。读取时检查TTL(成功60s、失败15s),过期则重新获取。

这种设计在”每次渲染都是新进程”的约束下优雅地实现了数据复用,将API调用频率从每300ms一次降低到每60秒一次。

5.3 macOS Keychain集成

用量数据显示需要OAuth accessToken,而ClaudeCode 2.x将其存储在macOS Keychain中。ClaudeHUD通过/usr/bin/security find-generic-password命令安全读取凭证:

const keychainData = execFileSync('/usr/bin/security',  ['find-generic-password''-s''Claude Code-credentials''-w'],  { encoding'utf8'stdio: ['pipe''pipe''pipe'],timeoutKEYCHAIN_TIMEOUT_MS });

安全措施包括:使用绝对路径和参数数组(避免shell注入)、超时保护(5000ms)、失败退避(60000ms期间不重试)、错误信息脱敏(不输出包含token的stderr/stdout)。

5.4 上下文窗口自动压缩预算

constants.ts中唯一的常量AUTOCOMPACT_BUFFER_PERCENT = 0.225是一个精巧的经验参数。ClaudeCode在上下文达到约77.5%时触发autocompact,这意味着用户看到的”100%”实际上会在autocompact发生时到达。通过在百分比计算中预先加入22.5%的缓冲区:

显示百分比 = (实际token + 22.5%窗口大小) / 窗口大小 × 100

使得显示值在autocompact时刻恰接近100%,提供了准确的心理预期。这种”向前看”的算法设计体现了对ClaudeCode内部行为的深入理解。

5.5 防御式配置合并

配置合并采用最保守的策略:逐字段验证类型和值域,任何验证失败都回退到硬编码默认值。这避免了常见的配置错误导致的全局故障模式。

5.6 Context百分比计算覆盖缓存Token

上下文百分比计算包含了缓存创建和缓存读取的输入token(cache_creation_input_tokenscache_read_input_tokens),这是通过对ClaudeCode stdin payload的深入分析后加入的修正——提示缓存虽然减少了API计费,但仍在上下文中占据空间。

6. 实践指南

6.1 安装与配置

安装分三步:

# 步骤1:添加marketplace/plugin marketplace add jarrodwatts/claude-hud# 步骤2:安装插件/plugin install claude-hud# 步骤3:配置状态行/claude-hud:setup

首次运行/claude-hud:setup时会进入交互式配置流程:选择预设(Full/Essential/Minimal),然后可逐项调整显示元素。

6.2 布局定制

三个预设满足不同使用场景:

  • Full预设:启用所有元素(工具、代理、Todo、Git、用量、时长),适合深度使用场景
  • Essential预设:启用活动行+Git状态,信息密度适中
  • Minimal预设:仅显示模型名称和上下文条形图,极简风格

预设选择后可通过/claude-hud:configure进行单项开关微调。高级设置(颜色、阈值、时间格式)需要直接编辑~/.claude/plugins/claude-hud/config.json

注意事项:

  • 配置更新后无需重启ClaudeCode即可生效(每次渲染独立加载配置)
  • JSON语法错误会导致静默回退到默认配置
  • pathLevels有效值为1/2/3,lineLayout有效值为expanded/compact

6.3 常见问题排查

  • HUD不显示:确认已运行/claude-hud:setup并重启ClaudeCode;在Windows上需要确保Node.js已安装
  • 用量数据不显示:确认使用的是订阅账户而非API密钥;Bedrock/Vertex用户不显示用量;非macOS平台可能无法获取OAuth凭证
  • 工具/代理/Todo行不显示:这些行默认隐藏,需要通过配置启用对应的showTools/showAgents/showTodos
  • Git状态缺失:确认当前目录在Git仓库内且gitStatus.enabled未设为false
  • Linux安装失败(EXDEV错误):设置TMPDIR=~/.cache/tmp后重新启动ClaudeCode

7. 总结

ClaudeHUD展示了如何以极简的代码(单模块约200行+5个渲染组件)构建一个功能完善的CLI状态仪表盘。

架构设计上最值得借鉴的几个决策:

  • 无状态进程+文件缓存的混合架构:兼顾了进程级故障隔离和跨渲染数据复用
  • 防御式配置合并:逐字段验证+静默回退,不会因用户输入错误而崩溃
  • 分层信息展示:核心层/活动层/环境层的三档显示梯度,兼顾信息密度和视觉简洁
  • 依赖注入设计:所有外部依赖通过接口抽象,测试时可直接注入mock

技术栈为纯TypeScript,无第三方运行时依赖(仅开发依赖TypeScript编译器和测试框架),使得插件体积极小、启动快速。约300ms的渲染间隔在实时性和系统开销之间取得了良好平衡。

适用场景:所有ClaudeCode高频用户,尤其是Pro/Max订阅用户(用量追踪)、在大型项目中并行使用多个子代理的用户(代理追踪)、以及需要精确掌握上下文窗口状态的用户。

对于想深入了解ClaudeCode插件开发或statusline API的开发者,ClaudeHUD的源码是一个高质量的参考实现。

参考文献

[1] ClaudeHUD项目仓库:https://github.com/jarrodwatts/claude-hud

[2] ClaudeCode官方文档:https://docs.anthropic.com/en/docs/claude-code