# How Claude HUD Reads CLAUDE.md, Rules, MCPs, and Hook Counts from Configuration

> Discover how Claude HUD reads CLAUDE.md, rules, MCPs, and hook counts. Learn about project-local and user-wide configuration scanning in src/config-reader.ts.

- Repository: [Jarrod Watts/claude-hud](https://github.com/jarrodwatts/claude-hud)
- Tags: how-to-guide
- Published: 2026-03-18

---

**Claude HUD aggregates counts for CLAUDE.md files, rules, MCP servers, and hooks by scanning both the user-wide `~/.claude` directory and the project-local `.claude` directory using the `countConfigs` function in [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts).**

Claude HUD is an open-source terminal interface for Claude Code that displays real-time configuration statistics. Understanding how the system reads counts for CLAUDE.md files, rules, MCPs, and hooks from the Claude HUD configuration helps developers debug environment setups and optimize their development workflow.

## Configuration Scopes and File Locations

The system operates across two distinct configuration scopes to aggregate counts. The **user-wide scope** resides at `~/.claude` and contains global settings applicable across all projects. The **project-local scope** uses the `.claude` directory within the current working directory, or any custom location specified by the `CLAUDE_CONFIG_DIR` environment variable.

When `countConfigs` executes in [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts), it resolves both paths and checks for overlapping locations to prevent double-counting. The function uses `pathsReferToSameLocation` to determine if the user directory and project directory point to identical filesystem locations, skipping redundant scans when they match.

## How CLAUDE.md Files Are Detected and Counted

The system identifies **CLAUDE.md** files by checking for the existence of [`CLAUDE.md`](https://github.com/jarrodwatts/claude-hud/blob/main/CLAUDE.md) and [`CLAUDE.local.md`](https://github.com/jarrodwatts/claude-hud/blob/main/CLAUDE.local.md) across both configuration scopes. In [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts) (lines 36‑86 and 71‑85), the logic checks the user home directory, project root, and optional `.claude/` sub‑folders for these specific filenames.

Each existing file increments the `claudeMdCount` variable. The function specifically looks for these two filename variants to support both shared project documentation ([`CLAUDE.md`](https://github.com/jarrodwatts/claude-hud/blob/main/CLAUDE.md)) and local-only overrides ([`CLAUDE.local.md`](https://github.com/jarrodwatts/claude-hud/blob/main/CLAUDE.local.md)).

## Counting Rules from Markdown Directories

Rules are markdown files (`.md`) stored within `rules` directories. The helper function `countRulesInDir()` in [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts) (lines 76‑92) walks the directory recursively and counts every file ending with the `.md` extension.

The function executes twice—once for the user’s `~/.claude/rules` directory and once for the project’s `./.claude/rules` directory—unless the paths overlap. This recursive scanning allows nested rule categorization while maintaining an accurate total count.

## Reading MCP Server Configurations

MCP server counts involve parsing JSON configuration files and filtering disabled entries. The system reads from three potential sources: [`settings.json`](https://github.com/jarrodwatts/claude-hud/blob/main/settings.json), side-car JSON files (`~/.claude.json` and [`./.mcp.json`](https://github.com/jarrodwatts/claude-hud/blob/main/./.mcp.json)), and custom `CLAUDE_CONFIG_DIR` JSON files.

The helper `getMcpServerNames()` in [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts) (lines 19‑27) parses these files and extracts the keys of the `mcpServers` object. Disabled servers are filtered using `getDisabledMcpServers()` (lines 33‑48), which checks both user-scope (`disabledMcpServers`) and project-scope (`disabledMcpjsonServers`) exclusion lists.

To prevent duplicates when the same server appears in both user and project configurations, the system stores results in two `Set` objects—one for user scope and one for project scope—and sums their sizes for the final `mcpCount`.

## Counting Hooks in Settings Files

Hooks are defined within [`settings.json`](https://github.com/jarrodwatts/claude-hud/blob/main/settings.json) files as top-level `hooks` objects. The function `countHooksInFile()` in [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts) (lines 62‑70) reads the specified JSON file and returns the number of keys present in the `hooks` object.

The system checks three specific locations: the user’s `~/.claude/settings.json`, the project’s [`.claude/settings.json`](https://github.com/jarrodwatts/claude-hud/blob/main/.claude/settings.json), and the local override [`.claude/settings.local.json`](https://github.com/jarrodwatts/claude-hud/blob/main/.claude/settings.local.json). Each valid hooks object contributes to the total `hooksCount`.

## Rendering Configuration Counts in the Terminal

Once collected, these counts flow to the terminal interface through the rendering pipeline. In [`src/index.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/index.ts) (line 54), the main entry point invokes `countConfigs` and destructures the results:

```typescript
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = await deps.countConfigs(stdin.cwd);

```

These values populate the `RenderContext` defined in [`src/types.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/types.ts), which passes to each line renderer. The **environment line** in [`src/render/lines/environment.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/render/lines/environment.ts) (lines 11‑33) determines visibility based on the `display.showConfigCounts` setting and an optional `environmentThreshold`. If the total count exceeds the threshold, the renderer constructs a pipe-separated string such as "2 CLAUDE.md | 5 rules | 3 MCPs | 1 hooks".

## Preventing Duplicate Counts Across Scopes

The system implements safeguards against double-counting when configuration scopes overlap. When the project-local `.claude` directory resolves to the same physical location as the user-wide `~/.claude` directory, the `pathsReferToSameLocation` check prevents redundant scanning.

For MCP servers specifically, the use of `Set` data structures ensures that identical server entries across user and project configurations only count once toward the total. Disabled server filtering occurs independently for both scopes, ensuring that a server disabled in the user configuration but enabled in the project configuration (or vice versa) respects the specific exclusion lists.

## Summary

- Claude HUD reads configuration counts from [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts), specifically the `countConfigs` function.
- The system scans two scopes: user-wide (`~/.claude`) and project-local (`.claude` or `CLAUDE_CONFIG_DIR`).
- **CLAUDE.md** counts include both [`CLAUDE.md`](https://github.com/jarrodwatts/claude-hud/blob/main/CLAUDE.md) and [`CLAUDE.local.md`](https://github.com/jarrodwatts/claude-hud/blob/main/CLAUDE.local.md) files across scopes.
- **Rules** are counted recursively from `rules/` directories using `countRulesInDir`.
- **MCP servers** are parsed from JSON configs with duplicates prevented via `Set` objects and disabled entries filtered via `getDisabledMcpServers`.
- **Hooks** are counted from `hooks` objects in [`settings.json`](https://github.com/jarrodwatts/claude-hud/blob/main/settings.json) files using `countHooksInFile`.
- The environment line in [`src/render/lines/environment.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/render/lines/environment.ts) displays counts when `showConfigCounts` is enabled and thresholds are met.

## Frequently Asked Questions

### How does Claude HUD prevent counting the same MCP server twice?

Claude HUD stores MCP server names in two separate `Set` objects—one for the user scope and one for the project scope. According to the source code in [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts), the final count is the sum of both sets' sizes, ensuring that identical server entries across scopes only contribute once to the total count.

### What happens if my project `.claude` folder is the same as my global `~/.claude` folder?

When the project-local configuration directory resolves to the same physical location as the user-wide directory, Claude HUD detects this overlap using the `pathsReferToSameLocation` helper. The system skips redundant scanning of the overlapping scope to prevent double-counting CLAUDE.md files, rules, and other configuration items.

### Can I disable specific MCP servers from being counted in the HUD?

Yes, Claude HUD respects disabled MCP server lists through the `getDisabledMcpServers` function in [`src/config-reader.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config-reader.ts). The system checks both user-scope (`disabledMcpServers`) and project-scope (`disabledMcpjsonServers`) exclusion lists, filtering out disabled servers before calculating the final MCP count displayed in the terminal.

### Where does the environment threshold setting control count visibility?

The `environmentThreshold` setting works alongside `display.showConfigCounts` in [`src/render/lines/environment.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/render/lines/environment.ts). If the sum of all configuration counts falls below this threshold value, or if `showConfigCounts` is disabled, the environment line returns `null` and hides the counts from the HUD display entirely.