Skip to main content
Thanks for contributing to Claude HUD. This repo is small and fast-moving, so we optimize for clarity and quick review.

Setup

1

Fork and clone the repo

Fork the repository on GitHub, then clone your fork:
git clone https://github.com/<your-username>/claude-hud.git
cd claude-hud
2

Create a branch

git checkout -b my-feature
3

Install dependencies

npm ci
4

Build the project

Compiles TypeScript from src/ to dist/:
npm run build
5

Run tests

npm test
npm test runs npm run build first, then executes Node’s built-in test runner. Keep execution under 5 seconds.

Build commands

CommandDescription
npm ciInstall dependencies
npm run buildCompile TypeScript to dist/
npm testBuild and run all tests
npm run test:coverageRun tests with coverage report (text + lcov)
npm run test:update-snapshotsRebuild golden-output snapshots

Testing your changes manually

After building, pipe a sample stdin JSON payload to the compiled binary to see live HUD output:
echo '{"model":{"display_name":"Opus"},"context_window":{"current_usage":{"input_tokens":45000},"context_window_size":200000}}' | node dist/index.js
Or use the built-in npm script, which includes a transcript_path field:
npm run test:stdin
The HUD is invoked every ~300ms by Claude Code. Each run receives a fresh JSON blob on stdin, parses the transcript JSONL, renders lines to stdout, and exits. Manual piping like this replicates that cycle.

Testing approach

Tests live in tests/ and are organized in three layers: Unit tests — pure helpers, rendering utilities, and transcript parsing logic. Deterministic and fast. Integration tests — run the CLI with a sample stdin JSON and a fixture transcript; assert the rendered output contains expected markers (model name, percent, tool names). Golden-output (snapshot) tests — compare full output against a stored snapshot. Update only when intentional output changes are made:
npm run test:update-snapshots
Fixtures are kept under tests/fixtures/ as small JSONL files, each capturing one behavior (basic tool flow, agent lifecycle, todo updates, etc.).

Contributing expectations

  • Add or update tests for behavior changes.
  • Prefer unit tests for new helpers and integration tests for user-visible output changes.
  • Keep tests deterministic — avoid time-dependent assertions unless controlled.

Project architecture

Data flow

Claude Code → stdin JSON → parse → render lines → stdout → Claude Code displays
           ↘ transcript_path → parse JSONL → tools/agents/todos
The statusline is invoked every ~300ms. Each invocation:
  1. Receives JSON via stdin (model, context window, token counts, transcript_path)
  2. Parses the transcript JSONL file for tool use, agents, and todos
  3. Renders multi-line output to stdout
  4. Claude Code displays all lines

Data sources

SourceData
stdin JSON (native, accurate)model.display_name, token counts, context_window_size, transcript_path
Transcript JSONLTool names, completion status, durations, todo list, agent info
~/.claude/settings.jsonMCP server count, hooks count
CLAUDE.md filesRules count
~/.claude/.credentials.jsonOAuth token and subscription type (when display.showUsage enabled)
Anthropic Usage API5h / 7d usage percentages, reset timestamps (cached 60s / 15s)

File structure

src/
├── index.ts           # Entry point
├── stdin.ts           # Parse Claude's JSON input
├── transcript.ts      # Parse transcript JSONL
├── config-reader.ts   # Read MCP/rules configs
├── config.ts          # Load/validate user config
├── git.ts             # Git status (branch, dirty, ahead/behind)
├── usage-api.ts       # Fetch usage from Anthropic API
├── types.ts           # TypeScript interfaces
└── render/
    ├── index.ts          # Main render coordinator
    ├── session-line.ts   # Compact mode: single line with all info
    ├── tools-line.ts     # Tool activity (opt-in)
    ├── agents-line.ts    # Agent status (opt-in)
    ├── todos-line.ts     # Todo progress (opt-in)
    ├── colors.ts         # ANSI color helpers
    └── lines/
        ├── index.ts         # Barrel export
        ├── project.ts       # Line 1: model bracket + project + git
        ├── identity.ts      # Line 2a: context bar
        ├── usage.ts         # Line 2b: usage bar (combined with identity)
        └── environment.ts   # Config counts (opt-in)

Dependencies

  • Runtime: Node.js 18+ or Bun
  • Build: TypeScript 5, ES2022 target, NodeNext modules
  • Dev: @types/node, c8 (coverage), typescript

Code style

  • Keep changes focused and small.
  • Prefer tests for behavior changes.
  • Avoid introducing dependencies unless necessary.

Build process

PRs should only modify files in src/ — do not include changes to dist/.
CI automatically builds and commits dist/ after your PR is merged. This keeps PRs focused on source code and makes review easier.
Your PR: src/ changes only → Merge → CI builds dist/ → Committed automatically

Submitting a pull request

  • Describe the problem and the fix.
  • Include tests or explain why they are not needed.
  • Link issues when relevant.
  • Only modify src/ files — CI handles dist/ automatically.

Code of conduct

Participation in this project is governed by our Code of Conduct. We pledge to make the community a harassment-free experience for everyone, regardless of background or identity. Unacceptable behavior includes harassment, discrimination, trolling, or publishing others’ private information without permission. Report violations to [email protected]. This Code of Conduct is adapted from the Contributor Covenant v2.1.

Build docs developers (and LLMs) love