mirror of
https://github.com/jarrodwatts/claude-hud.git
synced 2026-04-16 06:32:39 +00:00
8.1 KiB
8.1 KiB
Contributing to Claude HUD
Thanks for your interest in contributing! This guide will help you get started.
Community Standards
Please read CODE_OF_CONDUCT.md. For security issues, see SECURITY.md.
Development Setup
# Clone the repo
git clone https://github.com/jarrodwatts/claude-hud
cd claude-hud
# Install TUI dependencies
cd tui
bun install
# Build
bun run build
# Run tests
bun test
# Run with coverage
bun test --coverage
# Lint and typecheck
bun run lint
bun run typecheck
# Format code
bun run format
# Replay a fixture event stream
bun run replay:events -- --input ../tui/test-fixtures/hud-events.jsonl
One-shot checks
From the repo root:
./scripts/check.sh
Local Testing
To test the plugin locally without publishing:
# Create a symlink to your plugins directory
ln -sf $(pwd)/.. ~/.claude/plugins/claude-hud
# Verify installation
./scripts/verify-install.sh
# Start Claude with the plugin
claude --plugin-dir /path/to/claude-hud
Project Structure
claude-hud/
├── .claude-plugin/
│ └── plugin.json # Plugin manifest (name, version, hooks path)
├── hooks/
│ └── hooks.json # Hook event subscriptions
├── scripts/
│ ├── session-start.sh # Spawns HUD in split pane
│ ├── capture-event.sh # Captures events and sends to FIFO
│ ├── cleanup.sh # Cleans up on session end
│ └── verify-install.sh # Installation verification
├── docs/
│ ├── CHANGELOG.md # Version history
│ ├── research/ # Research notes
│ └── adr/ # Architecture Decision Records
├── tui/
│ ├── src/
│ │ ├── index.tsx # Entry point, session handling
│ │ ├── app.tsx # Main App component (slim)
│ │ ├── components/ # React/Ink UI components
│ │ │ ├── ContextMeter.tsx # Token usage + sparkline
│ │ │ ├── CostDisplay.tsx # API cost tracking
│ │ │ ├── ToolStream.tsx # Tool activity list
│ │ │ ├── AgentList.tsx # Subagent tracking
│ │ │ ├── StatusBar.tsx # Model + idle status
│ │ │ ├── SessionStats.tsx # Session statistics
│ │ │ ├── TodoList.tsx # Task tracking
│ │ │ ├── ContextInfo.tsx # CLAUDE.md detection
│ │ │ ├── Sparkline.tsx # Sparkline visualization
│ │ │ └── ErrorBoundary.tsx # Error handling
│ │ ├── hooks/
│ │ │ ├── useHudState.ts # Centralized state management
│ │ │ └── useElapsedTime.ts # Timer hook
│ │ └── lib/
│ │ ├── types.ts # TypeScript interfaces
│ │ ├── event-reader.ts # FIFO reader
│ │ ├── unified-context-tracker.ts # Token tracking (real + estimated)
│ │ ├── cost-tracker.ts # Cost estimation
│ │ ├── settings-reader.ts # Claude settings
│ │ ├── context-detector.ts # CLAUDE.md detection
│ │ └── logger.ts # Debug logging
│ ├── package.json
│ ├── tsconfig.json
│ ├── eslint.config.js # ESLint flat config
│ └── vitest.config.ts
├── README.md
├── CONTRIBUTING.md
├── TROUBLESHOOTING.md
└── LICENSE
Architecture
Data Flow
Claude Code → Hook Events → capture-event.sh → FIFO → EventReader → React State → UI
- Claude Code emits hook events (PreToolUse, PostToolUse, etc.)
capture-event.shreceives events and formats them as JSON- Events are written to a named pipe (FIFO)
EventReaderreads the FIFO and emits events- React components update based on state changes
Key Components
useHudState (hooks/useHudState.ts)
- Centralized state management hook
- Processes all events from EventReader
- Manages tools, agents, context, cost, todos
- Single source of truth for HUD state
EventReader (lib/event-reader.ts)
- Reads from named pipe (FIFO)
- Handles reconnection with exponential backoff
- Emits 'event' and 'status' events
UnifiedContextTracker (lib/unified-context-tracker.ts)
- Reads real tokens from transcript files when available
- Falls back to estimation when transcript unavailable
- Tracks burn rate and token history for sparkline
- Eliminates flickering from dual data sources
CostTracker (lib/cost-tracker.ts)
- Calculates cost based on token usage
- Supports different model pricing (Opus, Sonnet, Haiku)
- Tracks input/output tokens separately
Adding a New Panel
- Create a component in
tui/src/components/:
import React, { memo } from 'react';
import { Box, Text } from 'ink';
interface Props {
data: YourDataType;
}
export const YourPanel = memo(function YourPanel({ data }: Props) {
return (
<Box flexDirection="column" marginBottom={1}>
<Box>
<Text bold color="white">Your Panel</Text>
</Box>
{/* Panel content */}
</Box>
);
});
- Add state in
hooks/useHudState.ts:
const [yourData, setYourData] = useState<YourDataType>(initialValue);
- Process relevant events in the
processEventcallback:
if (event.event === 'RelevantEvent') {
setYourData(/* updated data */);
}
- Return the new state from
useHudState:
return {
// ... existing state
yourData,
};
- Add the component to
app.tsx(wrapped in ErrorBoundary):
<ErrorBoundary>
<YourPanel data={state.yourData} />
</ErrorBoundary>
- Add tests in
components/YourPanel.test.tsx.
Adding a New Hook
- Add the hook to
hooks/hooks.json:
"NewHookEvent": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/capture-event.sh",
"timeout": 5
}
]
}
]
-
Update
HudEventtype intypes.tsif new fields are needed. -
Handle the event in
processEventinindex.tsx.
Running Tests
cd tui
# Run all tests
bun test
# Run tests in watch mode
bun test:watch
# Run specific test file
bun test context-tracker
Code Style
- TypeScript strict mode - No implicit any
- React functional components - Use hooks, not classes
- No
anytypes - Useunknownor proper types - Ink components - Use Box, Text from ink for UI
- Error boundaries - Wrap components to prevent crashes
- React.memo - Use for all components to prevent unnecessary re-renders
- ESLint + Prettier - Run
bun run lintandbun run format - Pre-commit hooks - Husky runs lint-staged on commit
Quality Tools
# Lint (ESLint)
bun run lint
bun run lint:fix
# Format (Prettier)
bun run format
bun run format:check
# Type check
bun run typecheck
# All tests with coverage
bun test --coverage
Pull Requests
- Fork the repo
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Add tests for new functionality
- Run tests:
bun test - Build:
bun run build - Commit with descriptive message
- Submit PR
PR Checklist
- Tests added/updated
- TypeScript compiles without errors
- No console.log statements in production code
- Documentation updated if needed
- Tested locally with Claude Code
Areas for Contribution
Features
- Real token counting from transcript files
- More MCP server information
- Git branch/status display
- Custom themes
- Configuration file support
Improvements
- More terminal support
- Better error messages
- Performance optimization
- Accessibility improvements
Testing
- More component tests
- Integration tests
- Performance benchmarks
Documentation
- Video tutorials
- Architecture diagrams
- API documentation
Getting Help
- Open an issue for bugs or feature requests
- Check existing issues before creating new ones
- Join discussions in PRs
License
By contributing, you agree that your contributions will be licensed under the MIT License.