Thanks for contributing to Claude HUD. This repo is small and fast-moving, so we optimize for clarity and quick review.
Setup
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
Create a branch
git checkout -b my-feature
Build the project
Compiles TypeScript from src/ to dist/: Run tests
npm test runs npm run build first, then executes Node’s built-in test runner. Keep execution under 5 seconds.
Build commands
| Command | Description |
|---|
npm ci | Install dependencies |
npm run build | Compile TypeScript to dist/ |
npm test | Build and run all tests |
npm run test:coverage | Run tests with coverage report (text + lcov) |
npm run test:update-snapshots | Rebuild 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:
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:
- Receives JSON via stdin (
model, context window, token counts, transcript_path)
- Parses the transcript JSONL file for tool use, agents, and todos
- Renders multi-line output to stdout
- Claude Code displays all lines
Data sources
| Source | Data |
|---|
| stdin JSON (native, accurate) | model.display_name, token counts, context_window_size, transcript_path |
| Transcript JSONL | Tool names, completion status, durations, todo list, agent info |
~/.claude/settings.json | MCP server count, hooks count |
| CLAUDE.md files | Rules count |
~/.claude/.credentials.json | OAuth token and subscription type (when display.showUsage enabled) |
| Anthropic Usage API | 5h / 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.